I've been trying to create a type that consists of the keys of type T
whose values are strings. In pseudocode it would be keyof T where T[P] is a string
.
The only way I can think of doing this is in two steps:
// a mapped type that filters out properties that aren't strings via a conditional type
type StringValueKeys<T> = { [P in keyof T]: T[P] extends string ? T[P] : never };
// all keys of the above type
type Key<T> = keyof StringValueKeys<T>;
However the TS compiler is saying that Key<T>
is simply equal to keyof T
, even though I've filtered out the keys whose values aren't strings by setting them to never
using a conditional type.
So it is still allowing this, for example:
interface Thing {
id: string;
price: number;
other: { stuff: boolean };
}
const key: Key<Thing> = 'other';
when the only allowed value of key
should really be "id"
, not "id" | "price" | "other"
, as the other two keys' values are not strings.
ts-toolbelt
hasObject.SelectKeys
that could be useful. – Leifeste