【问题标题】:TypeScript: map strongly-typed collection [duplicate]TypeScript:映射强类型集合
【发布时间】:2018-07-18 20:39:16
【问题描述】:

我有一个强类型集合如下:

interface IUser {
  id: number,
  name: string
}

const users: IUser[] = [
  { id: 1, name: 'Bob' },
  // ...
];

然后,我使用map 函数创建一个新集合:

const nextUsers: IUser[] = users.map((user: IUser) => ({
  ID: 3, // wrong field name
  name: 'Mike',
  id: 3,
}));

如您所见,有一个名称错误的字段 - ID。好吧,问题是为什么work?))

【问题讨论】:

标签: javascript typescript


【解决方案1】:

这是 typescript 检查多余属性的副产品。一点背景:

如果类型 B 至少具有类型 A 的所有属性,则类型 A 通常可以从类型 B 分配。例如,执行此分配时不会出现错误:

let someObject = { id: 3, name: 'Mike', lastName: 'Bob' }
let user: { id: number, name: string } = someObject // Ok since someobject has all the properties of user
let userWithPass : { id: number, name: string, pass: string } = someObject // Error since someobject does not have pass

Typescript 唯一会抱怨属性过多的情况是当我们尝试直接将对象字面量分配给某个具有已知类型的对象时:

// Error excess property lastName
let user: { id: number, name: string } =  { id: 3, name: 'Mike', lastName: 'Bob' }

现在,在您的情况下,typescript 将首先将 map 的结果类型推断为返回的对象字面量的类型,这都是有效的,然后将检查此类型是否与 IUser 数组兼容就是这样,所以没有错误,因为我们从未直接尝试将对象字面量分配给 IUser 类型的东西。

如果我们显式设置传递给map的箭头函数的返回类型,我们可以确保得到错误

const nextUsers: IUser[] = users.map((user: IUser) : IUser => ({
    id: 3,
    name: 'Mike',
    ID: 152,
}));

【讨论】:

  • 谢谢!带有箭头函数类型的好提示!
【解决方案2】:

接口定义了对象必须具有的一些属性,但并不详尽;该对象也可以具有其他属性。这在文档here 中进行了演示。

【讨论】:

    【解决方案3】:

    它之所以有效,是因为定义了接口的属性。该接口不会阻止添加其他属性。

    但是:

    const nextUsers: IUser[] = users.map((user: IUser) => ({
      ID: 3, // wrong field name
      name: 'Mike',
    }));
    

    这会导致 TypeScript 编译器出错。

    【讨论】:

      【解决方案4】:

      它仍然可以工作,但如果你有一个打字稿 linter,你会遇到错误,因为返回的数组类型与 IUse[]

      【讨论】:

        猜你喜欢
        • 2019-01-12
        • 1970-01-01
        • 1970-01-01
        • 2017-08-08
        • 2019-03-21
        • 1970-01-01
        • 2018-02-05
        • 2015-07-04
        • 1970-01-01
        相关资源
        最近更新 更多