-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Template literal types fail in mapped types #42192
Comments
@ahejlsberg the output from this is fairly useless compared to expectation; should we make it an error? |
This should be fixed by #26797. |
Same issue with TypeScript v4.1.2: type FieldPattern = `/${string}`;
// Works as expected
const path1: FieldPattern = '/one'; // OK
const path2: FieldPattern = 'two'; // Type '"two"' is not assignable to type '`/${string}`'.ts(2322)
type PathsObject = { [P in FieldPattern]: object; };
const pathObject: PathsObject = 123; // No error. Why? TypeScript ignore any values. |
I found a workaround: type FieldPattern = `/${string}`;
type PathsObject<T extends FieldPattern = any> = { [P in T]: object; };
const pathObject1: PathsObject = 123; // Error as expected
const pathObject2: PathsObject<'/one'> = {'/one': {}}; // OK But I would like, of course, to have without bugs the version that I showed in the previous example. |
on this front maybe it is worth mentioning that types with such indexes also display other unexpected behaviors: type A = `A${string}`
type Akey = { [key in A]: string }
const a: Akey = { 'Ak': 'ira' }
a['Ak'] = 'ira' // --> this results in unexpected error I am unsure whether this is due to the same issue or is a different issue. |
✨ This is an old work account. Please reference @brandonchinn178 for all future communication ✨ In the following example, // all of these work as expected
type Foo = `${string}-${'end1' | 'end2'}`
let fooGood1: Foo = 'asdf-end1'
let fooGood2: Foo = 'asdf-end1'
let fooBad: Foo = 'asdf'
// Typescript evaluates this to `type Bar = {}`
type Bar = {
[K in Foo]: null
}
let barGood1: Bar = {
'asdf-end1': null,
'asdf-end2': null,
}
let barGood2: Bar = {
'asdf-end1': null,
'asdf-end2': null,
'hello-end1': null,
'hello-end2': null,
}
// these unexpectedly pass
let barBad1: Bar = {
'asdf-end1': null,
}
let barBad2: Bar = {
'asdf': null,
} |
Is this the same error? type IdType = `${number}-${number}-${number}-${number}`
const id: IdType = '0000-0000-0000-0001';
type A = Record<IdType, string>
const a: A = {
[id]: 'test'
}
a[id] // Element implicitly has an 'any' type because expression of type '`${number}-${number}-${number}-${number}`' can't be used to index type 'A'.(7053) |
Also, given |
Do we expect #26797 to ever be merged? If not, should this be fixed some other way? Or closed as a design limitation? |
Sorry for asking perhaps a stupid question, but does this now allow computed properties on class definitions? Something like: class Foo {
[key in 'foo' | 'bar']: string;
} or class Foo {
[key: 'foo' | 'bar']: string;
} |
Implemented in #44512 which is now in the main branch. |
@ahejlsberg Thanks for the response... Our use case is admittedly weird. Some of the libraries we are using in our stack use metadata reflection to generate Swagger definitions or ORM DDL from the TS side (NestJS Swagger Plugin, MikroORM) -- and the support for reflecting on classes seems much greater than that for pure You see the forest, I was looking for a way to water my tree. |
TypeScript Version: 4.1.3
Search Terms: template literal types
Expected behavior:
test
should not be able to pass the type-checking as its key 'someKey' is not of typePseudo
.Actual behavior:
test
passes the type-checking.The text was updated successfully, but these errors were encountered: