Reputation: 1160
I want a key of an interface to be added conditionally, for that use-case I tried doing
key: a extends b ? keyValue : never
but not only does that break when a
is generic, it also requires me to pass never as the value to the key ?
The questions are, how do I make that genric work and how to "filter" out never types so that I don't have to pass them explicitly.
Typescript Playground with the below example
export type Component<T extends ComponentList> = {
id: T;
kids: GetProps<T> extends { children: Record<string, any> } ? string[] : never;
};
// Change Wrapper to Button and you will see that kidType changes between string[] and never like it is supposed to
// But as an argument to reComponent it always thinks that the kids option is never, and it also asks me to give it a never option ??
type WrapperProps = GetProps<"Wrapper">
type kidType = WrapperProps extends {children: Record<string, any> } ? string[] : never;
const reComponent = <T extends ComponentList>(arg0: Record<string, Component<T>>) => {};
reComponent({
button1: {id: "Button" },
wrapper1: {id: "Wrapper", kids: [""]},
});
var Wrapper = ({
children,
}: {
children: Component<'Wrapper'> | Component<'Button'>
}) => {
return "react.component"
};
var Button = ({
text,
}: {
text: string
}) => {
return 123
};
var Components = {
Wrapper,
Button,
};
export type ComponentList =
| 'Wrapper'
| 'Button'
export type GetProps<T extends ComponentList> = Parameters<typeof Components[T]>[0];
Upvotes: 1
Views: 122
Reputation: 6089
Type never
cannot be used to remove a key from an interface. For example:
type testNever = {
x : string;
y : never;
}
var tn: testNever = { x: 'ab' } // error: property 'y' is missing
Type never
is meant to be used as the type of a function to indicate that it will never return. See TypeScript Handbook, section 'More on functions'
You can use the question mark to make a key optional and use keyword Required
to make a version of the type in which the key is required. Here is an example:
type TypeWithOptionalY = {
x : string;
y? : string;
}
type TypeWithRequiredY = Required<TypeWithOptionalY>
type WithOrWithoutY = 'requiredY' | 'optionalY'
type ConditionalY<T extends WithOrWithoutY> =
T extends 'requiredY'
? TypeWithRequiredY
: TypeWithOptionalY
var objWithoutY : ConditionalY<'optionalY'> = { x: 'abc' }
var objWithY : ConditionalY<'requiredY'> = { x: 'abc', y: 'def' }
Upvotes: 1