GeezerVison is showing github.com — Index signatures for symbols and template literal strings by ahejlsberg · Pull Request #44512 · microsoft/TypeScript
Conversation
With this PR we implement support for symbol and template literal string index signatures. We furthermore permit index signature declarations to specify union key types, provided all constituents are either string, number, symbol, or template literal types with non-generic placeholders. Some examples:
type SymbolMap<T> = {
[key: symbol]: T;
};
type DataProps = {
[key: `data-${string}`]: string;
};
type PropertyMap = {
[key: string | number | symbol]: string;
};
An index signature declaration that specifies a union key type is exactly equivalent to a set of distinct index signatures for each constituent key. For example, the PropertyMap declaration above is exactly equivalent to:
type PropertyMap = {
[key: string]: string;
[key: number]: string;
[key: symbol]: string;
};
Index signature declarations are not permitted to specify literal key types or generic key types. Those kinds of types can only be used with mapped types, which map literals key types to distinct properties and defer resolution of generic key types until they're instantiated with non-generic types. For example:
type Thing<T> = Record<'a' | `foo${T}` | symbol, string>;
type StringThing = Thing<string>; // { [a: string, [x: `foo${string}`]: string, [x: symbol]: string }
type BarThing = Thing<'bar'>; // { [a: string, foobar: string, [x: symbol]: string }
This PR supercedes #26797 which was more ambitious but had overlap between regular properties and index signatures with literal key types that is difficult to reconcile, as well as generic index signatures for which type relationships become exceedingly complex to reason about.
Fixes #1863.
Fixes #26470.
Fixes #42192.
Fixes #44675.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
c69-addepar, shellscape, tjjfvi, kamok, blake-regalia, KostyaTretyak, chocolateboy, ExE-Boss, leidegre, MingweiSamuel, and 49 more reacted with thumbs up emoji
kamok, MingweiSamuel, worstpractice, rbjakab, simonguo, and mishahrokhola reacted with laugh emoji
alexrock, konsalex, zhangenming, shellscape, tjjfvi, matso94, kamok, KisaragiEffective, ntucker, ExE-Boss, and 24 more reacted with hooray emoji
kamok, leidegre, MingweiSamuel, yortus, liuweiGL, VladSez, snewell92, worstpractice, dhaigh, Enteleform, and 8 more reacted with heart emoji
kamok, ExE-Boss, leidegre, MingweiSamuel, MatthiasKunnen, worstpractice, netweng, KilianKilmister, Enteleform, GitSquared, and 3 more reacted with rocket emoji
kamok, brainkim, andorthehood, rbjakab, simonguo, and mishahrokhola reacted with eyes emoji
All reactions
-
👍
59 reactions
-
😄
6 reactions
-
🎉
34 reactions
-
❤️
18 reactions
-
🚀
13 reactions
-
👀
6 reactions
|
Something is amiss with this, or it's not been released yet. Still receiving the 'ol error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead. errors. Ryan Cavanaugh (@RyanCavanaugh) can you confirm it's been released as of 4.3.5?
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Something is amiss with this, or it's not been released yet. Still receiving the 'ol error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead. errors. Ryan Cavanaugh (@RyanCavanaugh) can you confirm it's been released as of 4.3.5?
It's currently in the 4.4 release which is in beta scheduled to be released by the end of August.
|
shellscape and dlqqq reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Anders Hejlsberg (@ahejlsberg) Could you please clarify why those cases work differently in terms of assignability (playground)? AFAIU for a type alias and anonymous type it uses an empty literal type from getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode without resolving its members, but is it the expected behavior?
const sym = Symbol();
function gg3(x: { [key: string]: string }, z: { [sym]: number }) {
x = z; // Ok
}
interface GG4 {
[sym]: number;
}
function gg4(x: { [key: string]: string }, z: GG4) {
x = z; // Error
}
type GG5 = {
[sym]: number;
}
function gg5(x: { [key: string]: string }, z: GG5) {
x = z; // Ok ?!
}
|
c69-addepar and ExE-Boss reacted with eyes emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Is this in and working? I'm sitting on v4.4.2 and still receiving:
An index signature parameter type cannot be a union type. Consider using a mapped object type instead
type Test = 'one' | 'two';
export interface Foo {
[key: Test]: any;
}
|
ties-s, Cristy94, f-o-w-l, saadq, 307god, and sacru2red reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Douglas Gaskell (@douglasg14b)
You can do it using type and in (although not with interface).
type Test = 'one' | 'two';
type Foo= {
[key in Test]: any;
}
//type Foo = {
// one: any;
// two: any;
//}
type Foo2= {
[key in `${Test}${Test}`]: any;
}
//type Foo2 = {
// oneone: any;
// onetwo: any;
// twoone: any;
// twotwo: any;
//}
playground
I believe that because there is no "free" string or number template, this is old hat, and not related to this new feature.
|
douglasg14b, ExE-Boss, DevPres, steviebuilds, and markeljan reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Anders Hejlsberg (@ahejlsberg) - This is really a great feature, thanks!
I noticed that spaces seem to count as digits with the number type. How about not allowing that?
Of course with unquoted literal labels it doesn't matter, but with quoted string indices it does.
type TP4 = {[k:`${number}`]:null}
const tp4_1:TP4 = {'1':null}
const tp4_2:TP4 = {' ':null} // even though there is no number present, it passes
const tp4_3:TP4 = {' 1':null}
const tp4_4:TP4 = {'1 ':null}
const tp4_5:TP4 = {' 1 ':null}
playground
|
ExE-Boss reacted with eyes emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Index signatures for template literal string with generic?
type Props<T extends string> = {
renders: {[key in T]: any};
[key: `render${Capitalize<T>}`]: any;
};
TS 4.5.2 says:
An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.(1337)
|
leonardochaia, hellowalker, Thundercraft5, sacru2red, uladkasach, netotz, and jthoward64 reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
- If there're other keys needing restricting value type, how should I put it?
type Test = 'one' | 'two';
type Foo= {
stringKey: string; // A mapped type may not declare properties or methods.
numberKey: number;
[key in Test]: any;
}
playground
- Can this feature be used in interfaces?
enum Test {
ONE = 'one',
TWO = 'two'
}
interface Foo {
[key: Test]: any; // An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.
}
playground
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|