TypeScript 类型转换 [英] TypeScript type cast

查看:49
本文介绍了TypeScript 类型转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象,在某些情况下我需要向它添加一些额外的属性.

I have an object, and I need to add some extra properties to it in some cases.

interface Item {
    name: string
}

function addProp(obj: Item) {
    type WithFoo = Item & { foo?: string; }

    // The following does NOT work
    obj = obj as WithFoo;

    if (obj.name == 'test') {
        obj.foo = 'hello';
     }
}


似乎 obj = obj as AnotherType 不起作用,但如果我分配给另一个变量,它起作用,const anotherObj = obj as AnotherType.

It seems obj = obj as AnotherType does NOT work, but if I assign to another variable, it works, const anotherObj = obj as AnotherType.

有没有什么方法可以转换type引入另一个变量?

Is there any way to cast the type, without introducing another variable?

下面是在线游乐场

推荐答案

1.) 为什么 obj = obj as WithFoo 不起作用?有没有什么办法可以在不引入另一个变量的情况下强制转换类型?

1.) Why does obj = obj as WithFoo not work? Is there any way to cast the type, without introducing another variable?

首先obj函数参数变量声明为Item类型,所以TS不知道obj包含obj类型代码>{ foo?: string}.你的第二次机会是编译器的控制流分析用于分配,在这种情况下不能将 obj 类型缩小为 WithFoo,因为 obj 没有联合类型:

First of all the obj function parameter variable is declared with an Item type, so TS does not know that obj contains the type { foo?: string}. Your second chance would be the compiler's control flow analysis for assignments, which in this case cannot narrow the obj type to WithFoo, as obj does not have a union type:

将类型 S 的值赋值给类型 T 的变量(包括声明中的初始值设定项)会将该变量的类型更改为在赋值之后的代码路径中由 S 缩小的 T.

An assignment (including an initializer in a declaration) of a value of type S to a variable of type T changes the type of that variable to T narrowed by S in the code path that follows the assignment.

由 S 缩小的类型 T 计算如下:

The type T narrowed by S is computed as follows:

如果 T 不是联合类型,则结果为 T.
如果 T 是联合类型,则结果是 T 中 S 可分配给的每个组成类型的联合.

If T is not a union type, the result is T.
If T is a union type, the result is the union of each constituent type in T to which S is assignable.

这就是为什么您在示例中收到错误 Property 'foo' does not exist on type 'Item' 的原因.不是以下代码 将正确缩小和编译:

That is the reason, why you get the error Property 'foo' does not exist on type 'Item' in the example. Instead the following code would properly narrow and compile:

type WithFoo = { foo?: string; }

function addProp(obj: Item | WithFoo) {
    obj = obj as WithFoo;
    obj.foo = 'hello';
}

如果您不想重新赋值或引入另一个变量,可以使用内联 类型断言,通常可用于所有JavaScript 表达式:

If you don't want to do re-assignments or introduce another variable, foo property can be accessed with an inline type assertion, which in general is usable on all JavaScript expressions:

(obj as WithFoo).foo = 'hello';

话虽如此,更安全的方法可能是假设 obj 是联合类型 Item |WithFoo 并使用 type守卫而不是硬演员(见@Maciej Sikora的回答).

Having said that, a more safe way is probably to assume obj to be a union type Item | WithFoo and use type guards instead of a hard cast (see @Maciej Sikora's answer).

2.) 为什么 const anotherObj = obj as AnotherType 有效?

2.) Why does const anotherObj = obj as AnotherType work?

当你声明一个像 const anotherObj = obj as AnotherType 这样的新变量时,编译器会自动将变量 anotherObj 的类型推断为 AnotherType.TS 进行额外检查以确保 AnotherTypetypeof obj 兼容.例如.不会编译:

When you declare a new variable like const anotherObj = obj as AnotherType, the compiler automatically infers the type of variable anotherObj to AnotherType. TS does additional checks to make sure, AnotherType is compatible to typeof obj. E.g. this wouldn't compile:

function addProp(obj: Item) {
    const anotherObj = obj as string // error (OK)
    // ...
}

3.) 变量的类型在声明后可以改变吗?

不,letconst 变量 不能重新声明(var 具有相同的类型,但这里不重要),这意味着声明的变量类型也不能改变.不过,可以通过控制流分析来缩小变量范围,请参阅 1.).

Nope, let and const variables cannot be redeclared (var with same type, but not important here), which implies, the declared variable types also cannot be changed. The variables could be narrowed via control flow analysis though, see 1.).

这篇关于TypeScript 类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆