在Typescript中键入匿名对象而不使用类型断言

时间:2018-03-01 14:08:43

标签: typescript

考虑:

type Foo = {
   bar: string,
   baz: number
}

const bars = ['a', 'b', 'c'];
const foos = bars.map<Foo>((bar, i) => {
   return {
     bar,
     baz: i
   }
});

这将强制执行地图中返回值的确切类型,例如我可以说

return {
  bar,
  baz: i,
  extraProp: 'boo!'    // this works! (bad - i want this to fail)
}

它会正常工作。这与我没有使用泛型类型并在返回值上使用类型断言的效果相同:

return {
  bar,
  baz: i,
  extraProp: 'boo!'   // works (bad)
} as Foo

我可以想办法让实际类型完全强制执行的唯一方法是创建一个临时变量:

const returnVal: Foo = {
  bar,
  baz: i,
  // extraProp: 'boo!' // won't work - good! typescript prevented a bug!
}
return returnVal;

是否有任何语法允许创建匿名对象,例如在return语句中允许完全强制执行该类型,而不仅仅是类型断言?

1 个答案:

答案 0 :(得分:2)

问题是只有在将对象文字直接分配给参数/变量/返回值时才会检查对象文字的额外属性。当您在map上指定类型参数时,首先会使用此签名首先键入箭头函数:

(bar: string , i: number) => {    
    bar: string,
    baz: number,
    extraProp: string
}

然后检查此函数是否与map的参数兼容(键入为(bar: string , i: number) => Foo)并且将被发现兼容。

一个简单的解决方法是指定不在map上的类型,而是箭头函数的返回类型:

const foos = bars.map((bar, i): Foo => {
    return {
        bar,
        baz: i,
        extra: "" // error here, as expected
    }
});

这不是类型断言,但您确实需要指定类型,但无论如何都要在map上执行,因此输入的数量大致相同。