3

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.

1
  • Unrelated: in the edit queue, I came across a question that you voted on in triage. Wrong choice. Please: study the help for triage really carefully, and avoid putting items into the edit queue that don't belong there. ( I am specifically talking about stackoverflow.com/review/triage/20888979 ). Please understand that your votes have consequences! Commented Sep 18, 2018 at 7:50

1 Answer 1

3

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];
}
Sign up to request clarification or add additional context in comments.

4 Comments

That gives the correct type, but it for some reason doesn't work in generic context :( I'll open a new question about that.
Looks like I can't open a new question yet so I'll have to ask here. function getDate<T>(t: T, k: PropCompatible<T, Date>): Date { return t[k]; } fails to compile because TypeScript thinks that type of t[k] is not assignable to Date. Any ideas how to fix this?
@MikhailBurshteyn You need to put the constraint in a different way.. I'm on my phone right now, I'll try to add a version that will work for you, but I'll get to it on about an hour or so
@MikhailBurshteyn added a version that will work for you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.