Question
How do I create a template literal type that includes the indexed access of a union type parameter?
I am trying to use a template literal type for the return type of a generic function which doesn't seem to work well when indexing on the type parameter.
type IPhone = {
version: 1 | 2 | 3 | 4;
}
function getIPhoneName<T extends IPhone>(iPhone: T): `iPhone ${T['version']}` {
return `iPhone ${iPhone.version}`; // Error "Type '"iPhone 1"' is not assignable to type '`iPhone ${T["version"]}`'"
}
function getIPhoneName2<T extends IPhone['version']>(iPhoneVersion: T): `iPhone ${T}` {
return `iPhone ${iPhoneVersion}`; // Works
}
Fairly sure this issue has something to do with TypeScript not distributing the union, but unlike with conditionals, I don't see a way to force it to properly distribute. I also recognize that I could use as const
without the return type (see below), but this isn't as nice when working with generic classes (where this problem also appears).
function getIPhoneName3<T extends IPhone>(iPhone: T) {
return `iPhone ${iPhone.version}` as const;
}