Type Providers
Prerequisites: Projects and NuGet packages
A type provider generates types at compile time from an external source — a sample CSV or JSON file, a database schema, a web API description. You get autocompletion and type checking for data whose structure lives outside your code.
The best-known collection is FSharp.Data, with providers for CSV, JSON, XML, and HTML.
JSON provider
// illustrative: downloads FSharp.Data on first run
#r "nuget: FSharp.Data"
open FSharp.Data
type Weather = JsonProvider<"""
{ "city": "Oslo", "temperature": 3.5, "conditions": ["cloudy", "windy"] }
""">
let reading = Weather.Parse """
{ "city": "Lisbon", "temperature": 18.2, "conditions": ["sunny"] }
"""
printfn "%s: %.1f C" reading.City reading.Temperature
printfn "%A" reading.Conditions
Lisbon: 18.2 C
[|"sunny"|]
From the sample, the provider inferred a type with City: string,
Temperature: decimal, and Conditions: string[]. Mistype
reading.Temprature and you get a compile error, not a runtime
surprise. The sample can also be a file path or a URL.
CSV provider
// illustrative: downloads FSharp.Data on first run
#r "nuget: FSharp.Data"
open FSharp.Data
type Sales = CsvProvider<"region,product,amount\nNorth,Tea,120\n">
let data =
Sales.ParseRows "North,Tea,120\nSouth,Coffee,340\nNorth,Coffee,90"
data
|> Array.groupBy _.Region
|> Array.iter (fun (region, rows) ->
printfn "%s: %d" region (rows |> Array.sumBy _.Amount))
North: 210
South: 340
Columns become typed properties (Amount is an int, inferred from the
sample). For real files, use Sales.Load "sales.csv".
Other providers
- SQLProvider and FSharp.Data.SqlClient — typed SQL queries checked against a live database schema at compile time.
- SwaggerProvider — typed clients for OpenAPI/Swagger web APIs.
- FSharp.Data.GraphQL — typed GraphQL clients.
Trade-offs
- Providers that connect to a database or URL at compile time need that source available on every build machine (including CI) — or a cached schema file.
- Keep samples in the repository so builds are reproducible.
- Type providers are an F#-only feature: C# code can't use them directly, but it can use the resulting types if you expose them through normal records.