接口类型检查:直接分配失败,间接工作

时间:2018-12-20 10:49:11

标签: typescript

我很难理解,为什么将对象文字直接分配给变量(键入接口)失败,但是对完全相同的对象类型的间接分配进行检查。

考虑以下示例:

interface User { name: string }

// vs code complains: "only specify known properties"
const usr1 : User = {
  name: 'John',
  age: 42   // <- squiggly red line
}

// works
const usr2 : User = usr1;

usr1usr2都被键入为User,两者都接收相同的值。为什么Visual Studio代码只抱怨第一个? 是我不了解的IDE问题还是TypeScript概念?


详细说明

考虑扩展示例:

interface User { name: string }

// doesn't work
// const usr1 : User = {
//   name: 'John',
//   age: 42   // <- squiggly red line
// }

// assignment works obviously because usr3 is not typed to User
const usr3 = {
  name: 'Jane',
  age: 33
}

// works
const usr2 : User = usr3;


const getName = (u: User) => console.log(u.name);

getName(usr2);                       // works!
getName({ name: 'Jane', age: 33 });  // doesn't work!

这令人困惑! u的形式参数getName()接收完全相同的值。第一次有效,第二次无效。

1 个答案:

答案 0 :(得分:0)

对象文字在分配给其他变量或作为参数传递时会受到特殊对待,并进行多余的属性检查。如果对象文字具有“目标类型”所没有的任何属性,则会出现错误。

绕开这些检查实际上非常简单。最简单的方法是只使用类型断言:

let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

但是,如果您确定对象可以具有某些以特殊方式使用的额外属性,则更好的方法可能是添加字符串索引签名。如果SquareConfig可以具有上述类型的color和width属性,但是还可以具有许多其他属性,那么我们可以这样定义它:

interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

在这里,我们说SquareConfig可以具有任意数量的属性,只要它们不是颜色或宽度,它们的类型就无关紧要。

解决这些检查的最后一种方法(可能有点令人惊讶)是将对象分配给另一个变量:由于squareOptions不会进行过多的属性检查,因此编译器不会给您错误。

>
let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);

({https://www.typescriptlang.org/docs/handbook/interfaces.html,副标题为“多余的属性检查”)