Mikhail Burshteyn
Mikhail Burshteyn

Reputation: 5002

TypeScript type with properties of an object containing a specific type

I want to make a generic type CompatibleProp<T, U> which would resolve to a string type containing all the properties of T that hold values of type U.

Example of what I want to achieve:

class C {
    a: number;
    b: string;
    c: Date;
}

type DatePropOfC = PropCompatible<C, Date>;  // "c"
type NumberOrStringPropOfC = PropCompatible<C, number | string>;  // "a" | "b"
type AnyPropOfC = PropCompatible<C, any>;  // same as keyof C

Is this possible to achieve with TypeScript 2.8 conditional types? I've tried a few combinations can't find the right one.

Upvotes: 3

Views: 3356

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

Sure you can do this with conditional types and a extra type query

type PropCompatible<T, TProp> = { [P in keyof T] : T[P] extends TProp ? P : never}[keyof T]

Edit

While the above type works well for getting a union of keys of a certain type, in the context of a generic function it has the disadvantage that the compiler can't follow the fact that the property access will be of the given property type. To get this behavior we need to state the constraint that we only take keys of a given filed type in a different way. We can do this using an extra type parameter K for the key and mandate that for K the type of the field in T is of the given type (Date for example)

function getDate<T extends Record<K, Date>, K extends string>(t: T, k: K): Date {
    return t[k];
}

Upvotes: 3

Related Questions