Issue
I'm developing a library component that takes two generics (T, R) and as part of the input configuration, a boolean.
I'd like to enforce certain criteria on these three to throw typescript error for example if
someBoolean
is false,- T is string,
- R is object.
By object I mean any non primitive type i.e. an interface.
interface IConfig<T, R> {
someBoolean: boolean;
valueOutput(value: T): R;
}
@Component({
selector: 'example',
template: `
<p>I'm an example component!</p>
`,
})
export class ExampleComponent<T, R> {
@Input() selectOptions: T[] = [];
@Input() config: IConfig<T, R> = {
someBoolean: true,
valueOutput: (v) => v as any as R, // TODO: throw if valueOutput not provided and T, R different
};
}
Explicitly I'm looking to enforce the following:
someBoolean T R Allowed
false string string Yes
false string number No
false string object No
false number string No
false number number Yes
false number object No
false object string Yes
false object number Yes
false object object No
true string string Yes
true string number No
true string object No
true number string No
true number number Yes
true number object No
true object string Yes
true object number Yes
true object object Yes
I know how to do this with javascript objects but struggling to find a way with abstract generics.
What I've tried
I can obviously create explicit interfaces for some of these and create a union type. I don't know how to tell typescript IConfig<T, R>
should be one of these given I get a type rather than an interface at the end. Also a little lost on how to tell typescript generic T is an interface rather than some primitive type.
interface IConfigBase1<T = string, R = string> {
someBoolean: false;
}
...
interface IConfigBase10<T = object, R = object> {
someBoolean: true;
}
type IConfigBase =
| IConfigBase1
...
| IConfigBase10;
Solution
type B = string|number|object
type P <T, R, S extends boolean >= {
someBoolean: S;
valueOutput:(value: T)=> R;
}
type IConfig<T extends B, R extends B> = T extends string
? R extends string
? P<T, R, boolean>
: never
: T extends number
? R extends number
? P<T, R, boolean>
: never
: R extends object
? P<T, R, true>
: P<T, R, boolean>;
Answered By - lisonge
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.