I wasn’t sure how to word this question. I have a scenario where I have an object. Key1 is the name, key2 is options. Options type depends on the value of name.
This works ok, thanks to:
export type Option1 = {
one: string;
};
export type Option2 = {
two: string;
};
export type Name = 'first' | 'second';
export type Options<TName extends Name> = TName extends 'first'
? Option1
: TName extends 'second'
? Option2
: never;
type Baz<TName extends Name> = { name: TName, opts: Options<TName> }
Now I wish to use this in an object.
type MyObj = {
foo: boolean,
bar: string,
baz: Baz[]
}
The goal is to do something like this:
const test: MyObj = {
baz: [ { name: 'first': opts: .. }, { name: 'second': opts: .. }]
}
With it being all typed correctly. If name
is ‘first’, then opts
is typed to only have key one
. However, MyObj
complains that I need to pass in a generic type to Baz, which makes sense, but I’m not sure what or how. I tried type Baz<TName extends Name = Name>
to default it, but this just makes all my values a union of all options, where opts is one
and two
keys.
How can i restrict this type?
>Solution :
You can achieve it in a very simple way using union type:
export type Option1 = {
one: string;
};
export type Option2 = {
two: string;
};
export type NameWithOptions =
| { name: 'first'; opts: Option1[] }
| { name: 'second'; opts: Option2[] };
type MyObj = {
foo: boolean;
bar: string;
baz: NameWithOptions[];
};
const test: MyObj = {
baz: [
{ name: 'first', opts: [{ one: 'one' }] },
{ name: 'second', opts: [{ two: 'two' }] },
],
};