繁体   English   中英

如何在 TypeScript 中索引对象类型?

[英]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'给我的类型。

我可以使用asx转换为字典类型:

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'

操场

在此处查看我的回答以获取有关in运算符和此问题的更多上下文/43284

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM