如何通过强制转换来缩小打字稿类型,错了?

Siy*_*iya 1 typescript

我正在运行一个用打字稿编写的 javascript 应用程序。在代码的某处我有这样的东西

{
  title: props.value?.name as string
}
Run Code Online (Sandbox Code Playgroud)

一个朋友告诉我,这不是一个好的类型转换方法,因为我们假装 undefined 不存在。我不明白这一点,因为这很有效,而且我看不到它会破裂。

你能向我解释一下如何通过类型转换来缩小打字稿类型,不好,永远不应该这样做吗?

Cer*_*nce 5

如果您需要使用可选链,那么您不知道该属性是否实际存在:

const props = {
    value: Math.random() < 0.5 ? undefined : { name: 'foo' }
};
const someObj = {
    title: props.value?.name as string
}
Run Code Online (Sandbox Code Playgroud)

如果value结果是undefined,那么someObj将是:

{
    title: undefined
}
Run Code Online (Sandbox Code Playgroud)

但该title属性仍将被输入为字符串,这意味着您可以这样做

someObj.title.startsWith('bar')
Run Code Online (Sandbox Code Playgroud)

这将引发运行时错误,最终由不正确的类型断言引起。

由于您不知道value对象是否存在,您应该键入titleas string | undefined,以防可选链接失败 - 这样,someObj.title在对它的使用字符串方法之前,引用必须将其缩小为字符串:

const props = {
    value: Math.random() < 0.5 ? undefined : { name: 'foo' }
};
const someObj = {
    title: props.value?.name as (string | undefined)
    // above type assertion not necessary if TS can already recognize
    // that it's a string or undefined
    // like in this example
};
if (someObj.title) {
    console.log(someObj.title.startsWith('bar'));
} else {
    console.log('it is undefined');
}
Run Code Online (Sandbox Code Playgroud)

如果您确实知道该value对象存在,并且它的name属性是一个字符串,则删除可选链接:

const someObj = {
    title: props.value.name as string
};
Run Code Online (Sandbox Code Playgroud)