interface Type1 {
attr1: string;
attr2: string;
}
interface Type2 {
attr1: string;
attr2: string;
attr3: string; // extra attribute
}
function fn(config: Type1 | Type2): void {
// Property 'attr3' does not exist on type 'Type1 | Type2'.ts(2339)
const { attr1, attr2, attr3 } = config;
console.log(attr1);
console.log(attr2);
console.log(attr3);
}
Error code show before. And I know there is a solution that add optional attribute in attr3
. But as far as I'm concerned this solution is not good. Because as matter of fact there only exist 2 situations either Type1
or Type2
. In a word, optional way is not readability. How can I fix it in advanced way?
You could just simply check if attr3
exists in the object
function fn(config: Type1 | Type2): void {
if ('attr3' in config) {
const {
attr1,
attr2,
attr3
} = config;
} else {
const {
attr1,
attr2
} = config;
}
}
Or you could use a custom type guard
function IsType2(config: Type1 | Type2): config is Type2 {
return (config as Type2).attr3 !== undefined;
}
function fn(config: Type1 | Type2): void {
if (IsType2(config)) {
const {
attr1,
attr2,
attr3
} = config;
} else {
const {
attr1,
attr2
} = config;
}
}
Or if we really wanted to destructure only once, we could create a join type, though we would be coercing the type rather than inferring it.
function fn(config: Type1 | Type2): void {
const {
attr1,
attr2,
attr3
} = config as Type1 & Type2;
}
As far as I know, there's no way to directly destructure a union type
If you want to get the same result when missing attr3
attribute as with js
code you can just cast config type to intersection of types:
interface Type1 {
attr1: string;
attr2: string;
}
interface Type2 {
attr1: string;
attr2: string;
attr3: string; // extra attribute
}
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
function fn(config: Type1 | Type2): void {
// Property 'attr3' does not exist on type 'Type1 | Type2'.ts(2339)
const { attr1, attr2, attr3 } = config as UnionToIntersection<Parameters<typeof fn>[0]>;
console.log(attr1);
console.log(attr2);
console.log(attr3);
}
fn({ attr1: '', attr2: '' })
or just to ... = config as Type1 & Type2;
if you don't mind some inflexibility.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.