Luckylooke
Luckylooke

Reputation: 4549

How to reference derived types in typescript?

Having object A:

interface A {
   boolProp: boolean,
   stringProp: string,
   numberProp: number,
   ...other props/methods...
}

Then I want to have objects, which holds one of the A properties and defines default value for it, other properties are irrelevant to this issue.

interface B {
    prop: keyof A,
    default: typeof keyof A,
   ...other props/methods...
}

I want to get TS error when I try to set default value of different type

const b: B = {
  prop: 'stringProp',
  default: true, // expecting to get TS error as true cannot be assigned to string
};

Thank you in advance for any help 🙏

Upvotes: 1

Views: 1060

Answers (2)

geoffrey
geoffrey

Reputation: 2474

Another approach is to use a generic. It won't create a union type:

interface B<T extends keyof A> {
    prop: T,
    default: A[T]
//    ...other props/methods...
}

const b: B<'stringProp'> = {
  prop: 'stringProp',
  default: true, // error
};

Of course the repetition of 'stringProp' is annoying. You may use a function or a class constructor instead and check the arguments passed to it, for example:

const createB = <T extends keyof A>(prop: T, defaultVal: A[T]) => ({ prop, default: defaultVal });

const b = createB('stringProp', true);
// error                        ----

Upvotes: 1

Tobias S.
Tobias S.

Reputation: 23925

You essentially want a union type which holds all valid prop/default combinations. This can be programmatically generated with a mapped type which maps over the keys of A and is indexed with keyof A.

type B = {
    [K in keyof A]: {
        prop: K
        default: A[K]
    }
}[keyof A] & {
    /* ... put all the other props of B here */ 
}

Playground

Upvotes: 1

Related Questions