I have to create a component that can be from two different types. Let's say
Type A = { a: SomeCustomType }
Type B = { b: SomeOtherDifferentType }
As far I understand, I can define that component type as
function Component<T extends A | B>(props T){ ... Stuff }
And i can call it as
const MyComponent : A = <Component a={"test"}/>
const MyComponent : B = <Component b={1231241}/>
My question here is: when coding Component
, how can i navigate props, i need to do:
function Component<T extends A | B>(props T){
let data;
if(props typeof A){
data = props.a
}
if(props typeof A){
data = props.b
}
console.log(data)
}
I'm not able to use typeof
since it's for primitives, but instanceOf seems for classes only. Any clues about this? What i'm doing wrong?
CodePudding user response:
There is no real clean solution for that, since types don't exist in the resulting JavaScript.
I'ld advise you do add a shared field like type
in both types which helps to TypeScript to figure out which properties are available:
type A = { a: string, type: "A" }
type B = { b: string, type: "B" }
function Component<T extends A | B>(props: T) {
switch (props.type) { // or: if (props.type === "A") ...
case 'A':
// access props.a, TypeScript will infer it's there
break;
case 'B':
// access props.b, TypeScript will infer it's there
break;
}
}
The advantage of this approach is that is scales quite well with more - and more complex types.
Edit: In general, type checks can be done with a user-defined type guard:
const isTypeA = (toCheck: A | B): toCheck is A => 'a' in toCheck;
function Component<T extends A | B>(props: T) {
if (isTypeA(props)) {
// access props.a, TypeScript will infer it's there
}
}
But I'ld stick with the first variant in most cases. It's less error prone (the type guard method could be faulty) and delivers the aforementioned advantages.
CodePudding user response:
You could try something like this:
type A = { a: string }
type B = { b: number }
function Component<T extends A | B>(props: T){
let data;
if ('a' in props){
data = props.a
} else if ('b' in props){
data = props.b
}
console.log(data)
}
TypeScript will automatically detect type of props according to checks in if
statements. Try in playground