https://github.com/microsoft/TypeScript/pull/39577
any is really unknown and never?any biting us.https://github.com/microsoft/TypeScript/pull/37910
Foo | Bar | Baz to Target, have to cacheFoo | Bar | Baz to TargetFoo to TargetBar to TargetBaz to Targetundefined | null | T.https://github.com/microsoft/TypeScript/pull/26797
data- and aria-."foo" - finite"foo" | "bar" - finitestring - infinite`aria-${string}` - infinite`aria-${string}`.{ [x: T]: Type } where T is generic.T in those cases.number is assignable to string.isRelatedToisRelatedTo does the nice logic.What about
interface Foo {
[x: `aria-${string}`]: string;
[x: `aria-yadda-${string}`]: boolean;
}
https://github.com/microsoft/TypeScript/issues/26242
Out-of-time
@DanielRosenwasser if you're curious for a case of how higher order index types become useful, consider the validation case:
interface AriaProps<TStateProps extends "busy" | "current" | "disabled" | "grabbed" | "hidden" | "invalid"> {
[x: `aria-${string}`]: string;
[x: `aria-${TStateProps}`]: "true" | "false";
}
offers validation that all the possible properties produced by the second index signature are assignable to the index signature type (if the possible values overlap, which they do). Imagine we had instead written:
interface AriaProps<TStateProps extends "busy" | "current" | "disabled" | "grabbed" | "hidden" | "invalid"> {
[x: `aria-${string}`]: string;
[x: `aria-${TStateProps}`]: true | false;
}
the compiler would be able to warn us of our mistake - aria-busy is of type boolean, which is not assignable to the aria-${string} index signature of type string. Whereas the equivalent mapped type:
type AriaProps<TStateProps extends "busy" | "current" | "disabled" | "grabbed" | "hidden" | "invalid"> = {
[x: `aria-${string}`]: string;
} & {
[x in `aria-${TStateProps}`]: true | false;
}
would have no such validation, and simply produce a never upon reading each of the specified properties. There are _usability_ reasons why generic index signatures should exist. Mapped types are definitely more powerful - the 1-to-1 correspondences they represent allow for powerful remappings of both keys, values, and modifiers, none of which are something an index signature could reasonably do without constraining when it could do them in strange ways, while index signatures play an important role in ensuring object consistency and intent - the same way overload signatures need to be consistent with the implementation.
Most helpful comment
@DanielRosenwasser if you're curious for a case of how higher order index types become useful, consider the validation case:
offers validation that all the possible properties produced by the second index signature are assignable to the index signature type (if the possible values overlap, which they do). Imagine we had instead written:
the compiler would be able to warn us of our mistake -
aria-busyis of typeboolean, which is not assignable to thearia-${string}index signature of typestring. Whereas the equivalent mapped type:would have no such validation, and simply produce a
neverupon reading each of the specified properties. There are _usability_ reasons why generic index signatures should exist. Mapped types are definitely more powerful - the 1-to-1 correspondences they represent allow for powerful remappings of both keys, values, and modifiers, none of which are something an index signature could reasonably do without constraining when it could do them in strange ways, while index signatures play an important role in ensuring object consistency and intent - the same way overload signatures need to be consistent with the implementation.