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

Jam*_*rgy 6 typescript

考虑:

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

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

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

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

它会正常工作。这与我没有使用泛型类型并在返回值上使用类型断言一样:

return {
  bar,
  baz: i,
  extraProp: 'boo!'   // works (bad)
} as Foo
Run Code Online (Sandbox Code Playgroud)

我能弄清楚要完全强制执行实际类型的唯一方法是创建一个临时变量:

const returnVal: Foo = {
  bar,
  baz: i,
  // extraProp: 'boo!' // won't work - good! typescript prevented a bug!
}
return returnVal;
Run Code Online (Sandbox Code Playgroud)

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

Tit*_*mir 5

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

(bar: string , i: number) => {    
    bar: string,
    baz: number,
    extraProp: string
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

这不是类型断言,但您确实需要指定类型,但map无论如何您都会这样做,因此键入的数量大致相同。