Whenever I have to work with objects that have a bined union type, typescript plains about the properties that I try to access and I don't get autopletion either. For example this:
interface A {
id: string;
value: number;
}
interface B {
result: string;
}
export type Types = A | B;
function test(obj: Types) {
obj.result; // want to work with obj as though it implements interface B
}
I get errors when I access result
, id
, and value
from typescript:
Property 'result' does not exist on type 'Types'.
Property 'result' does not exist on type 'A'
Is there any way that I can narrow down the interface type so that I would get a better IDE experience?
Whenever I have to work with objects that have a bined union type, typescript plains about the properties that I try to access and I don't get autopletion either. For example this:
interface A {
id: string;
value: number;
}
interface B {
result: string;
}
export type Types = A | B;
function test(obj: Types) {
obj.result; // want to work with obj as though it implements interface B
}
I get errors when I access result
, id
, and value
from typescript:
Property 'result' does not exist on type 'Types'.
Property 'result' does not exist on type 'A'
Is there any way that I can narrow down the interface type so that I would get a better IDE experience?
Share Improve this question asked Jul 15, 2020 at 8:08 LoupiLoupi 5807 silver badges18 bronze badges 2- You need a type guard in one way or another. – Yoshi Commented Jul 15, 2020 at 8:11
-
Because
result
only exists onB
, if yourobj
is aA
, then accessingresult
on it will returnundefined
– Trash Can Commented Jul 15, 2020 at 8:11
3 Answers
Reset to default 6interface A {
type:'A';
id: string;
value: number;
}
interface B {
type:'B';
result: string;
}
export type Types = A | B;
function test(obj: Types) {
if(obj.type==='B'){
obj.result;
}
}
You need a mon field to teach TS how to recognize type A or B.
https://www.typescriptlang/docs/handbook/advanced-types.html#discriminated-unions
If you want that action you can use &
operator
like
type Types = A & B
you can merge A interface and B interface. It's naming Intersection Types
And I can write some info about this. Can you wait some minutes?
Reference
- About & Intersection Types
- About Union Tpyes
And now I know that what I got it was wrong. So if you want to use type gaurd it's work for you.
enum ALPHA_TYPE {
A = "A",
B = "B"
}
interface A {
...
}
interface B {
...
}
export type Types<T extends ALPHA_TYPE> = T extends A ? A : B
function test<T>(obj: Types<T>) {
obj.result; // want to work with obj as though it implements interface B
}
and you can use like
text<ALPHA_TYPE.A>()
interface A {
id: string;
value: number;
}
interface B {
result: string;
}
type Types = A | B;
function test(obj: Types) {
const objB = obj as B; // Introduce a new variable and cast it as B
objB.result; // Happy!!!
}
Just introduce a new variable and cast it to B, then you get to call .result
on the object.