![](/img/trans.png)
[英]How can I test if Object has value by key without ignoring TypeScript warning: 'string' can't be used to index type?
[英]How can I index into an object type in TypeScript?
我的应用程序收到“消息”。 我首先验证未知输入以确保它遵循预期的消息格式:
const isMessage = x =>
typeof x === 'object' &&
x !== null &&
typeof x['data'] === 'string';
我希望在 TypeScript 中输入它。 这是我所拥有的:
type Message = { data: string };
const isMessage = (x: unknown): x is Message =>
typeof x === 'object' &&
x !== null &&
typeof x['data'] === 'string';
但是,这无法进行类型检查,因为:
Element implicitly has an 'any' type because expression of type '"data"' can't be used to index type '{}'.
Property 'data' does not exist on type '{}'.
在类型保护typeof x === 'object' && x !== null
,TypeScript 给出了类型x : object
。 这似乎与x : {}
相同。 但是这种类型不允许我检查对象的任何属性。
而不是x: object
,我想我想要一个“字典”类型,比如x: { [key: string | number | symbol]: unknown }
x: { [key: string | number | symbol]: unknown }
x: { [key: string | number | symbol]: unknown }
。 但这不是 TypeScript 从类型保护typeof x === 'object'
给我的类型。
我可以使用as
将x
转换为字典类型:
const isMessage = (x: unknown): x is Message =>
typeof x === 'object' &&
x !== null &&
typeof (x as { [key: string | number | symbol]: unknown })['data'] === 'string';
这种类型检查,但它真的很长而且笨拙,而且我不确定as
类型转换是否真的类型安全。
我读到了in
操作符缩小,基于此,我预计'data' in x
中添加'data' in x
会起作用:
const isMessage = (x: unknown): x is Message =>
typeof x === 'object' &&
x !== null &&
'data' in x &&
typeof x['data'] === 'string';
然而,这没有区别; TypeScript 仍然抱怨我无法索引到x
,即使在x
中的'data' in x
点。 为什么这个in
运算符不允许我索引到x
?
你应该可以这样做:
type Message = { data: string };
const isMessage = (x: unknown): x is Message =>
typeof x === 'object' &&
x !== null &&
typeof (x as Message).data === 'string';
这种技术显示在 TypeScript 的文档中: https : //www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
由于typeof
也是运行时检查,所以as
断言不会消除任何类型安全性。
你可以这样想:在最后一行之前,我们已经检查过x
是一个对象并且不是null
。 因此,即使x
是{}
或{bar: 'bar'}
或{data: null}
, x.data
也不会在运行时失败。 我们只需要使用断言使编译器允许我们这样做运行时typeof
检查。
您可以使用通用的hasProperty
助手进行属性检查:
type Message = { data: string };
const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
: obj is Obj & Record<Prop, unknown> =>
Object.prototype.hasOwnProperty.call(obj, prop);
const isMessage = (x: unknown): x is Message =>
typeof x === 'object' &&
x !== null &&
hasProperty(x, 'data') &&
typeof x['data'] === 'string'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.