json const assertion import
The ability to get const types from a json configuration file.
IE if the json is:
{
appLocales: ["FR","BE"]
}
I want to import the json and get the type {appLocales: "FR" | "BE"}
instead of string
Current approach gives a too broad type string
. I understand it may make sense as a default, but having the possibility to import a narrower type would be helpful: it would permit me to avoid maintaining both a runtime locale list + a union type that contains the values that are already in the list, ensuring my type and my runtime values are in sync.
My suggestion meets these guidelines:
This feature has been mentionned:
This would be extremely useful for adding direct support for JSON schemas to TypeScript. This can technically be accomplished with generators right now, but it would be so much more elegant to be able to use mapped types (for example, https://github.com/wix-incubator/as-typed) to map an imported JSON schema to its corresponding TypeScript type. It isn't currently possible to use this approach with a JSON import since the type
property of each schema object will be a string
instead of 'boolean' | 'string' | 'number' | ...
.
FWIW I just tried to do this and used the exact same syntax that the issue title uses, if that's any indication of how intuitive it is 😁
I just tried the exact above syntax also. Const assertion is a fantastic tool and it would be incredible to have the ability to assert static json files at import
I added a note to #26552 and now realize that I put it in the wrong place, so copying it over here :D
Reading JSON more literally into string types would be a significant improvement to be able to put configs into JSON.
As an example, the WordPress Gutenberg project is moving towards a JSON registration schema for multiple reasons. The list of available category options could and should be tightly limited to the available options. However, due to this bug, we could never enforce a proper category list which effectively breaks TS linting of the file for anyone wanting to use TS when creating Gutenberg blocks or plugins.
I've been trying to work on a fix for some of these issues here: https://github.com/pabra/json-literal-typer. If your use-case is relatively straightforward (limited special characters, no escape characters in string literals), then it may satisfy some needs. Would love to have this built-in to the language, but hopefully this will be helpful to some in the interim.
// CC: @DanielRosenwasser @RyanCavanaugh
How about syntax import const ConstJson from './config'
and limited for the json modules.
I'm happy to work on this if it could be accept.
@Kingwl I think this syntax could be slightly more confusing than the alternatives. It could look similar to the import name when viewed in a sequence of imports. It would be good to get some a view on what the preferred syntax would be for everyone.
1 - import const myJson from './myJson.json';
2 - const import myJson from './myJson.json';
3 - import myJson from './myJson.json' as const';
Personal view:
const foo = 'abc'
. I think this would at first pass look more like a variable assignment than an importThoughts? Have I missed any alternative syntax options?
Also happy to work on this if it progresses!
I'm for option #3. This one looks similar to the current "as const" syntax:
const x = {...} as const
It makes it more intuitive. Definitely a killer feature for config-based code if Typescript adopts it.
As great as this suggestion is, how should TypeScript interpret the type of property in the original comment?
{
"appLocales": [ "FR", "BE" ]
}
readonly [ "FR", "BE" ]
[ "FR", "BE" ]
("FR" | "BE")[]
string[]
_← the current one_I think, there's no way for TypeScript to know the desired level of strictness without developer explicitly specifying it somehow, — and it looks like this will have to be done per each file, rather than once in _tsconfig.json_
I think I'm gonna answer my own question 🙂
The const
keyword in as const
is not much about inferring the types literally, as it is about declaring the value as immutable, read-only, sealed. _That in turn_ helps to infer the types more literally, without the worry about being too specific.
With this in mind, it would be intuitive and expected to set the output of *.json modules to be read-only, forbidding any mutable operation on them. This would make it work just like it currently is working with runtime objects and as const
assertion.
@parzhitsky I think most would agree on the 1st suggestion, as it is coherent with the present as const
statement, and as it is the narrowest option (other types can easily be derived from it if needed).
This is getting even more valuable after Variadic Tuple Types since we can create more types based on the json values, think of json files used for localization so we can extract interpolation. Any thoughts on implementing this yet?
For the last half-year or so I have been forcing this behavior by having a somewhat kludgy pre-compile step that reads in a config.json
like {"thing":"myVal"}
and exports it as a config.ts
like export const Config = {"thing":"myVal"} as const;
and use the resulting type definition on the imported json. (previously I needed to do a lot more, prepending readonly
everywhere to get the desired array behavior, but at some point that all became unnecessary). It is very helpful during development!
Configuration will likely vary at runtime and thus the content of the json import cannot be known; nevertheless, a as const
compiled json delivers on all of TypeScript's primary design goals. I can report that having used it to wrangle over-sized configuration json, it has been invaluable in:
That is to say, from a pragmatic perspective, import config from './config.json' as const
does most of the things that I find TypeScript most helpful for.
@RyanCavanaugh you set this as "Awaiting more feedback" - it has 110 thumbs up and a load of comments from people who would find the feature useful. Can it be considered now or at least the tags changed? Or does it require more people to add to the emoji's ?
@RyanCavanaugh This feature would be very helpful for json-schema-to-ts. You could define and use JSON schemas on one side (API Gateway, swagger... whatever!), and use them in the TS code to infer the type of valid data. Less code duplication, more consistency, everyone would be happier!
Most helpful comment
I'm for option #3. This one looks similar to the current "as const" syntax:
It makes it more intuitive. Definitely a killer feature for config-based code if Typescript adopts it.