TypedPaths by Alex Chim
NuGet / site data
Details
Info
Name: TypedPaths
A Roslyn source generator that turns a folder tree into strongly typed path constants at compile time.
Author: Alex Chim
NuGet: https://www.nuget.org/packages/TypedPaths.Generator/
You can find more details at https://github.com/AlexChim1231/TypedPaths/
Author
Alex Chim

Original Readme
TypedPaths.Generator
A Roslyn source generator that turns configured folder trees into strongly typed path constants at compile time. Each configured folder becomes a nested static class (for example Src, Template) so you can avoid magic strings.
What you get
Given a structure like:
/src
Template1.anyext
folderA/
Template2.anyext
folderB/
Template3.anyext
Template4.anyext
/template
email/
welcome.txt
sms/
otp.txt
the generator emits one file per root folder (TypedPaths.Src.g.cs, TypedPaths.Template.g.cs, ...), each defining a top-level static class in the TypedPaths namespace:
// TypedPaths.Src.g.cs
// <auto-generated/>
namespace TypedPaths;
public static class Src
{
public const string Value = "src";
public static class Template1
{
public const string Value = "src/Template1.anyext";
}
public static class FolderA
{
public const string Value = "src/folderA";
public static class Template2
{
public const string Value = "src/folderA/Template2.anyext";
}
}
public static class FolderB
{
public const string Value = "src/folderB";
public static class Template3
{
public const string Value = "src/folderB/Template3.anyext";
}
public static class Template4
{
public const string Value = "src/folderB/Template4.anyext";
}
}
}
// TypedPaths.Template.g.cs
// <auto-generated/>
namespace TypedPaths;
public static class Template
{
public const string Value = "template";
public static class Email
{
public const string Value = "template/email";
public static class Welcome
{
public const string Value = "template/email/welcome.txt";
}
}
public static class Sms
{
public const string Value = "template/sms";
public static class Otp
{
public const string Value = "template/sms/otp.txt";
}
}
}
With using TypedPaths; you can use Src.FolderA.Template2.Value and Template.Email.Welcome.Value instead of raw string paths.
Requirements
- .NET 8 (or the TFM your project uses; the generator targets .NET Standard 2.0)
- MSBuild / SDK-style projects
Setup
######### Option A: consume from NuGet (recommended)
<ItemGroup>
<PackageReference Include="TypedPaths.Generator" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<TypedPathsFolder Include="src" ClassName="Src" />
<TypedPathsFolder Include="template" />
</ItemGroup>
That is the only configuration needed in consumer projects.
TypedPaths.Generator.targets (from package build) automatically maps each TypedPathsFolder to AdditionalFiles for source generation.
######### Option B: local project reference (repository development)
<ItemGroup>
<ProjectReference Include="..\TypedPaths.Generator\TypedPaths.Generator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
<ItemGroup>
<TypedPathsFolder Include="src" ClassName="Src" />
<TypedPathsFolder Include="template" />
</ItemGroup>
<Import Project="..\TypedPaths.Generator\build\TypedPaths.Generator.targets"
Condition="Exists('..\TypedPaths.Generator\build\TypedPaths.Generator.targets')" />
The explicit <Import /> is required only for local project-reference scenarios.
Build the project; the generator runs and adds TypedPaths.*.g.cs files to the compilation.
Usage in code
Add using TypedPaths; and use the generated classes directly. Each configured root folder becomes a top-level static class (e.g. Src, Template):
using TypedPaths;
// Always read .Value (works for both folder and file nodes)
string folderPath = Src.FolderA.Value; // "src/folderA"
string filePath = Src.FolderA.Template2.Value; // "src/folderA/Template2.anyext"
string emailTemplate = Template.Email.Welcome.Value; // "template/email/welcome.txt"
// e.g. resolve to full path
var fullPath = Path.Combine(projectRoot, Src.FolderA.Template2.Value);
Value is always a path relative to the project root:
- Folder node
Value= relative folder path - File node
Value= relative file path (including extension)
Nested child classes are emitted only for folders (because only folders can contain files/subfolders).
Naming rules
- Folder and file names become PascalCase identifiers.
- Invalid identifier characters are dropped or split; leading digits get a
_prefix. - Duplicate names in the same scope get suffixes:
_2,_3, etc. - Extensions are stripped from member names but kept in the path string.
- If a folder name and file name conflict in the same scope:
- the folder keeps the base name;
- the file name becomes
FileName + ExtensionWithoutDot(example:report/+report.txt->ReportandReportTxt); - if the conflicting file has no extension, use
Filesuffix (example:data/+data->DataandDataFile).
Repository layout
| Project | Description |
|---|---|
TypedPaths.Generator | The source generator (Roslyn incremental generator). |
TypedPaths.Generator.Sample | Example app that uses the generator and runs a small demo. |
TypedPaths.Generator.Tests | Unit tests for the generator. |
Build and test
dotnet restore
dotnet build
dotnet test
Run the sample:
dotnet run --project TypedPaths.Generator.Sample
License
See the repository for license information.
About
Generating strongly-typed paths for file system operations in C# projects.
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
This is the CSharp Project that references TypedPaths
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TypedPaths.Generator" Version="1.3.0" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<TypedPathsFolder Include="a" ClassName="Src" />
<!--<TypedPathsFolder Include="template" />-->
</ItemGroup>
</Project>
This is the use of TypedPaths in Program.cs
Console.WriteLine("Hello, World!");
Console.WriteLine(TypedPaths.Src.Andrei.Value);
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- TypedPaths.Src.g.cs
- TypedPathsAttribute.g.cs
// <auto-generated/>
namespace TypedPaths;
public static class Src
{
public const string Value = "a";
public static class Andrei
{
public const string Value = "a/andrei.txt";
}
}
namespace TypedPaths
{
[System.AttributeUsage(System.AttributeTargets.Class)]
internal class TypedPathAttribute : System.Attribute \{ }
}
Useful
Download Example (.NET C#)
Share TypedPaths
https://ignatandrei.github.io/RSCG_Examples/v2/docs/TypedPaths
Category "FilesToCode" has the following generators:
1 Chorn.EmbeddedResourceAccessGenerator
2024-01-21
2 corecraft
2024-02-17
3 Datacute.EmbeddedResourcePropertyGenerator
2024-11-03
4 DotnetYang
2024-06-29
5 EmbedResourceCSharp
2023-04-16
6 kli.Localize
2025-10-01
7 LingoGen
2024-02-23
8 NFH.FileEmbed
2025-08-08
9 NotNotAppSettings
2024-01-26
10 Podimo.ConstEmbed
2023-04-16
11 ResXGenerator
2023-10-02
12 RSCG_JSON2Class
2024-02-29
13 RSCG_Utils
2023-04-16
14 Strings.ResourceGenerator
2025-07-06
15 ThisAssembly_Resources
2023-09-16
16 ThisAssembly.Strings
2024-07-21
17 TypedPaths
2026-04-01
18 Weave
2024-01-27