[英]Why Typescript throw error message: Property does not exist on type?
I created two code examples.我创建了两个代码示例。 The only difference between them is what expression I pass to the switch operator.
它们之间的唯一区别是我传递给 switch 运算符的表达式。
In a first case I use an object property.在第一种情况下,我使用 object 属性。 And it works fine.
它工作正常。
In a second case I create a type
variable.在第二种情况下,我创建了一个
type
变量。 And Typescript throw an error message:并且 Typescript 抛出错误信息:
Property 'name' does not exist on type 'Action'.
“操作”类型上不存在属性“名称”。
Property 'name' does not exist on type '{ type: "reset";
类型 '{ type: "reset"; 上不存在属性 'name' }'.
}'。
Why is this happening?为什么会这样?
The object property action.type
and variable type
are of the same type 'reset' | 'update'
object 属性
action.type
和变量type
属于同一类型'reset' | 'update'
'reset' | 'update'
. 'reset' | 'update'
。
interface State { name: string; cars: any[]; } type Action = { type: 'reset' } | { type: 'update', name: string }; function reducer(state: State, action: Action): State { switch (action.type) { case 'update': return {...state, name: action.name }; case 'reset': return {...state, cars: [] }; default: throw new Error(); } }
interface State { name: string; cars: any[]; } type Action = { type: 'reset' } | { type: 'update', name: string }; function reducer(state: State, action: Action): State { /** * Create a 'type' variable */ const { type } = action; switch (type) { case 'update': return {...state, name: action.name }; /** * Typescript will throw an error message * Property 'name' does not exist on type 'Action'. * Property 'name' does not exist on type '{ type: "reset"; }'. */ case 'reset': return {...state, cars: [] }; default: throw new Error(); } }
Basically, Typescript doesn't keep track of a relationship between the types of the variables action
and type
;基本上, Typescript 不会跟踪变量
action
和type
的类型之间的关系; when type
's type is narrowed (such as in a case
of a switch
statement), it doesn't also narrow action
's type.当
type
的类型被缩小时(例如在switch
语句的case
),它也不会缩小action
的类型。
On the assignment const { type } = action;
关于赋值
const { type } = action;
, the compiler infers type: Action['type']
, which happens to be 'reset' | 'update'
,编译器推断
type: Action['type']
,恰好是'reset' | 'update'
'reset' | 'update'
. 'reset' | 'update'
。 Later, the case
expression doesn't narrow the type of action
because no type-guarding check was done on action
.后来,
case
表达式并没有缩小action
的类型,因为没有对action
进行类型保护检查。
For this to behave the way you want it to behave, the compiler would have to introduce a type variable T extends Action['type']
and infer type: T
, while simultaneously narrowing action
to the type : Action & { type: T }
.为了让它按照你希望的方式运行,编译器必须引入一个类型变量
T extends Action['type']
并推断type: T
,同时将action
缩小到 type : Action & { type: T }
. Then when type
's type is narrowed, T
itself would have to be narrowed, so the effect would propagate to action
's type which would involve T
.然后当
type
的类型变窄时, T
本身也必须变窄,因此效果会传播到涉及T
的action
的类型。
Introducing a new type variable like this on every variable assignment, and control-flow narrowing the upper bounds of type variables, would greatly complicate the type-checking algorithm.在每个变量赋值中引入一个像这样的新类型变量,并且控制流缩小类型变量的上限,会使类型检查算法大大复杂化。 It would also greatly complicate the inferred types making them harder for users to understand;
这也会使推断类型变得非常复杂,使用户更难理解; so it's reasonable that Typescript doesn't do this.
所以 Typescript 不这样做是合理的。 Generally speaking, type-checkers don't prove every provable property of your code, and this is an example.
一般来说,类型检查器并不能证明代码的所有可证明属性,这是一个示例。
When you refer to the argument it can infer the type from the whole object but when you create a constant you limit the type to simply become "reset" | "update"
当您引用参数时,它可以从整个 object 中推断出类型,但是当您创建一个常量时,您将类型限制为简单地变为
"reset" | "update"
"reset" | "update"
and the other bits of Action object type info is lost. "reset" | "update"
和 Action object 类型信息的其他位丢失。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.