打字稿交集类型T无法分配给T&U类型

时间:2020-06-28 20:53:10

标签: typescript

typescript handbook

中所述

交集类型将多种类型组合为一种。这样,您便可以将现有类型加在一起,以获得具有所需所有功能的单个类型。

这是扩展功能

function extend<T extends object, U extends object>(first: T, second: U): T & U {
  const result = <T & U>{};
  for (let id in first) {
    (<T>result)[id] = first[id];
  }
  for (let id in second) {
    if (!result.hasOwnProperty(id)) {
      (<U>result)[id] = second[id];
    }
  }

  return result;
}

const x = extend({ a: 'hello' }, { b: 42 });

变量result被声明为类型T&U 。因此它应该在类型U和类型T上都具有两者属性,对吧?

当我们迭代类型T的属性时,为什么将result声明为类型T

  for (let id in first) {
    // I'm confused about code below 
    (<T>result)[id] = first[id];
  }

我认为不需要将result设置为T类型,但出现了错误

  for (let id in first) {
    result[id] = first[id];
    // error
    //Type 'T[Extract<keyof T, string>]' is not assignable to type '(T & U)[Extract<keyof T, string>]'.
    //Type 'T' is not assignable to type 'T & U'.
    // Type 'object' is not assignable to type 'T & U'.
    // Type 'object' is not assignable to type 'T'.
    // 'object' is assignable to the constraint of type 'T', but 'T' could be instantiated with a 
    //  different subtype of constraint 'object'.
  }


有人可以解释该错误,并在错误发生时给出更具体的代码示例吗?

1 个答案:

答案 0 :(得分:0)

问题是当您的两种类型TU共享具有不同类型的属性名称时。考虑这种情况:

interface Button { state: 'OFF' | 'ON' }
interface Dial { state: 'OFF' | 1 | 2 | 3 }

let button = { state: 'ON' };
let dial = { state: 3 };

let obj = {} as Button & Dial;

// this property has type 'OFF', otherwise it can't be both a Button and a Dial
obj.state

// this is a type error because button.state isn't necessarily a valid Dial state
obj.state = button.state;
// this is a type error because dial.state isn't necessarily a valid Button state
obj.state = dial.state;

这不是技术性知识;通常,您的函数不是类型安全的,因为它并不总是返回有效的T和有效的U两者。编译器正确,在此处给出错误。如果您知道仅将使用共享属性一致(或没有共享属性)的类型调用函数,则只能使用类型断言来使错误静音。

Playground Link