Description
(This seems to have some things in common with #6080 and is strongly related to #1295 as it can be used to provide an alternative solution to it but l opened this separately since I did not feel it was appropriate to continue discussing it there and wanted to approach it in a more generalized way)
This would provide improved type safety for cases where an interface property is referenced through a string having a value that's known at compile time:
type MyType = { "ABC": number };
let x: MyType = { ABC: 42 };
const propName = "ABC"; // 'propName' received the literal type "ABC" (not string)
let y = x[propName]; // 'y' received the type MyType["ABC"] which resolved to 'number'
And with support for generic types added, this could work similarly, but resolve to an intermediate type of the form T[S]
where T
is an object type and S
is a string literal type:
function func<T extends object>() {
let x: T;
const propName = "ABC"; // 'propName' received the literal type "ABC"
let y = x[propName]; // 'y' would receive the type T["ABC"]
}
This could combine with readonly
function parameters to provide an alternative solution for #1295 (which was actually where the idea was initially proposed):
function getProperty<T extends object, S extends string>(obj: T, readonly propName: S): T[S] {
return obj[propName];
}
// Here T resolves to { ABC: number }, S resolves to the literal type "ABC",
// and T[S] resolves to number
let x = getProperty({ABC: 42}, "ABC"); // Type of 'x' is number
// Here T resolves to { ABC: number }, S resolves to the literal type "CBA"
// and T[S] resolves to any
let x = getProperty({ABC: 42}, "CBA"); // Type of 'x' is any
// Here T resolves to { ABC: number }, S resolves to string
// and T[S] resolves to any
let x = getProperty({ABC: 42}, getRandomString()); // Type of 'x' is any
This may similarly extend to numeric literal types, for tuples:
type MyTupleType = [number, string, boolean];
let x: MyTupleType;
const index = 1; // 'index' received the literal type 1;
let y = x[index]; // 'y' received the type MyTupleType[1] which resolved to 'string'
And work with generic tuples as well:
function getTupleElement<T extends Array<any>, N extends number>(tuple: T, readonly index: N): T[N] {
return tuple[index];
}
Same can be done with symbol literal types (haven't thought about that much though):
function getSymbolProperty<T extends object, S extends symbol>(obj: T, readonly sym: S): T[S] {
return obj[sym];
}