0

I'd like a way to have an interface with a single generic, in which a property is keyof T and the other is the proper T[keyof T] passed on the first property.

The following code almost meets this requirement, correctly typing the first property (field):

interface RandomType {
    foo: string;
    bar: number;
    baz: boolean;
}

type Typer<T = Record<string, any>> = {
    field: keyof T,
    value: T[any]
}

const param: Typer<RandomType> = {
    field: 'baz',
    value: 'foo'
}

However, I need to type value based on field's value

in the previous example, it should trigger a type error because RandomType['baz'] is boolean

2 Answers 2

1

You want Typer<T> to be a union of field/value pairs for each field in T. You can do this a number of ways. For example:

type Typer<T> = { [K in keyof T]: {
    field: K,
    value: T[K]
} }[keyof T];

Here we are mapping over the properties in T to get a new object whose values are the types you want, and then immediately looking up all its values.

You can verify that Typer<RandomType> is what you're looking for:

type TyperRandomType = Typer<RandomType>
/* type TyperRandomType = {
    field: "foo";
    value: string;
} | {
    field: "bar";
    value: number;
} | {
    field: "baz";
    value: boolean;
} */

and then your example gives the error you expect:

const param: Typer<RandomType> = {
    field: 'baz',
    value: 'foo'
}; // error!
// Types of property 'value' are incompatible.
// Type 'string' is not assignable to type 'boolean'

Playground link to code

Sign up to request clarification or add additional context in comments.

Comments

0

This would do what you want, but right now you have to specify the key twice:

type Typer<T, K extends keyof T> = {
    field: K,
    value: T[K]
}

const param: Typer<RandomType, 'baz'> = {
    field: 'baz',
    value: 'foo' // Type 'string' is not assignable to type 'boolean'. ts(2322)
}

I think there is an open issue for TS to make it possible to only specify some generics and infer the rest, so that Typer<RandomType> would work.

1 Comment

Probably the most relevant issue on the matter: github.com/microsoft/TypeScript/issues/26242

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.