-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
import ConstJson from './config.json' as const; #32063
Comments
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 |
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 |
@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.
Personal view: #1 - As mentioned above, not sure it's optimal due to distance from import name Thoughts? 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" ]
}
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 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 |
@parzhitsky I think most would agree on the 1st suggestion, as it is coherent with the present |
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 Configuration will likely vary at runtime and thus the content of the json import cannot be known; nevertheless, a
That is to say, from a pragmatic perspective, |
@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! |
Chiming in to add another use case: with the new recursive mapped types + string transformations we would like to parse the ICU syntax in translation files in order to extract the params needed to translation strings. Here's a simplified example: type ParserError<E extends string> = { error: true } & E
type ParseParams<T extends string, Params extends string = never> = string extends T ? ParserError<'T must be a literal type'> : T extends `${infer Prefix}{${infer Param}}${infer Rest}` ? ParseParams<Rest, Params | Param> : Params
type ToObj<P extends string> = { [k in P] : string }
const en = {
"Login.welcomeMessage": "Hello {firstName} {lastName}, welcome!"
} as const
declare function formatMessage<K extends keyof typeof en>(key: K, params: ToObj<ParseParams<typeof en[K]>>): string;
formatMessage('Login.welcomeMessage', {firstName: 'foo' }) // error, lastName is missing
formatMessage('Login.welcomeMessage', {firstName: 'foo', lastName: 'bar' }) // ok This currently requires |
Related: #40694 Implement Import Assertions (stage 3) |
I also found my way here because I ran into type errors when trying to use a JSON module in a somewhat strongly typed context. In addition to the already mentioned use cases, being able to import JSON modules " import { AsyncApiInterface } from "@asyncapi/react-component"
import React from "react"
import schema1 from "./schema1.json"
import schema2 from "./schema2.json"
function dropdown(schemas: readonly AsyncApiInterface[]) {
return (
<select>
{schemas.map(schema => <option>{schema.info.title}</option>)}
</select>
)
}
dropdown([ schema1, schema2 ]) // type error at the time of writing EDIT: One would even be able to statically express for example that the current schema must be one of the existing/supported/listed schemas (and not just any schema): import { AsyncApiInterface } from "@asyncapi/react-component"
import React from "react"
import schema1 from "./schema1.json"
import schema2 from "./schema2.json"
import schema3 from "./schema3.json"
type Props<Schemas extends readonly AsyncApiInterface[]> = {
schemas: Schemas
currentSchema: Schemas[keyof Schemas]
}
class SchemaList<Schemas extends readonly AsyncApiInterface[]> extends React.Component<Props<Schemas>> {
render() {
const { currentSchema, schemas } = this.props
return (
<ul>
{schemas.map(schema => (
<li style={schema === currentSchema ? { backgroundColor: "#66BBFF" } : undefined}>
{schema.info.title}
</li>
))}
</ul>
)
}
}
<SchemaList
schemas={[ schema1, schema2 ] as const}
currentSchema={schema3} // Would be a (much appreciated) type error because it's not in `schemas` (unless schema3 is exactly identical to one of them).
/> |
Possible workaround (if your file is called Now import as normal to get the literal type. |
To avoid "The expression of an export assignment must be an identifier or qualified name in an ambient context." (TS2714) errors, use:
|
Not a drop-in workaround for json const, but you can type a json file manually. @mattpocock has a little article on it: https://www.totaltypescript.com/override-the-type-of-a-json-file |
@slorber Unfortunately |
Hi I found this issue since I think it would be a great addition to infer Types from Json Schemas! See ThomasAribart/json-schema-to-ts#200 Happy to help if someone can point me in the right direction. |
This change makes it easier to work with the ISO 639-3 codes returned by Zenodo. Note I had to replicate the mapping from the iso-639-3 library as TypeScript widens string value types. I've also had to exclude 'hbs' as the iso-639-1 library doesn't include the equivalent code 'sh'. As it's deprecated, this shouldn't be a problem. Refs #1739, microsoft/TypeScript#32063
as a workaround, should we implement a simple converter json2js, it would take a my.json file an create a my.js file. //my.json //my.js all it needs to do is to add the first line and then we can |
What do you do when the json filename is an invalid symbol name, i.e. it has hyphens? |
@couhajjou-apps @GabenGar
|
@couhajjou-apps If we're going that route, I'd rather use default export rather than the named one to avoid dependending on the arbitrary filename: - {
+ export default {
"foo": 42,
"bar": 17
} |
I don't see how it's related and why it has 3 thumbs up. Weird. |
Good idea ! |
Import hyphenJson from './-.json' with { type: 'json' } This discussion isn't about importing JSON modules nor is it about importing them with an attribute so it's imported only with a JSON parser (that was resolved by https://github.com/tc39/proposal-json-modules). This discussion is about getting the type information from the imported object as if it was an object defined with the TypeScript syntax const arr0 = [
"entry0",
1,
];
// typeof arr === (string | number)[]
const arr1 = [
"entry0",
1,
] as const;
// typeof arr1 === [ "entry0", 1 ] If they want |
The exact thing that There are still some annoying type narrowing / widening problems that can arise, but |
Search Terms
json const assertion import
Suggestion
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 ofstring
Use Cases
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.Checklist
My suggestion meets these guidelines:
Links:
This feature has been mentionned:
The text was updated successfully, but these errors were encountered: