简体   繁体   中英

TypeScript function generic types intersection does not behave correctly

interface A {
  a: number;
}

let myVar: A = {
  a: 123
};

myVar = Object.assign({}, myVar, {
  b: 456
});

Why does TypeScript not complain about that re-assignment of myVar via the Object.assign() call?

Given that the type definition for that Object.assign() call is:

assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;

...and the (return type) intersection of the three types in my call doesn't match interface A , shouldn't the compiler pick that up?

The problem is not related to TypeScript not being able to infer the types in the function call, because if I change the code to:

interface A {
  a: number;
}

interface B {
  b: number;
}

interface C {}

let myVar: A = {
  a: 345
};

myVar = Object.assign<C, A, B>({}, myVar, {
  b: 345
});

...it still doesn't complain.

I'm using TypeScript 2.2.1 and the "noImplicitAny" compiler flag is set to "true".

The basic rule for TypeScript's structural type system is that x is compatible with y if y has at least the same members as x

Applying this rule to your example - A is compatible with A&B&C :

let abc:A&B&C = {a:123, b:456};

And assignment let a:A = abc; is perfectly valid.

More info here

A & B is assignable to X if A is assignable to X or B is assignable to X .

Given that TypeScript uses a structural type system , the reason there is no error is because the re-assignment of myVar gets the properties from the source/original myVar (second argument) and is satisfied from then on. So any other objects that get mixed in (eg first and third arguments), are irrelevant when it comes to satisfying the type of myVar .

Quote source

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM