TypeScript 类型转换 [英] TypeScript type cast
问题描述
我有一个对象,在某些情况下我需要向它添加一些额外的属性.
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 进行额外检查以确保 AnotherType
与 typeof 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.) 变量的类型在声明后可以改变吗?
不,let
和 const
变量 不能重新声明(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屋!