如何将对象安全地转换为Record

时间:2020-09-23 21:02:38

标签: typescript

如何安全地将打字稿object转换为Record<PropertyKey, unknown>?例如,当读取JSON时,您会得到一个any对象,该对象实际上应该是unknown(我认为不是为了向后兼容):

const ob = JSON.parse("{}") as unknown;

我可以使用类型断言将unknown转换为object

if (typeof ob !== "object" || ob === null) {
  throw new Error("Not an object");
}
// Typescript now infers the type of ob as `object`

但是,现在我应该做什么检查才能说服Typescript将其视为Record<PropertyKey, unknown>是安全的?可能有object个不是Record个吗?

我确定必须要说,但是我不是在寻找ob as Record<PropertyKey, unknown>

2 个答案:

答案 0 :(得分:0)

类似于注释中提到的io-ts,请查看zod以了解您的用例:https://github.com/vriad/zod/

import * as z from 'zod';

// I believe this kind of circular reference requires ts 3.7+
type JsonValue =
  | { [index: string]: JsonValue }
  | JsonValue[]
  | boolean
  | null
  | number
  | string;

type JsonObject = { [index: string]: JsonValue } | JsonValue[];

const valueSchema: z.ZodSchema<JsonValue> = z.lazy(() => {
  return z.union([
    z.record(valueSchema),
    z.array(valueSchema),
    z.boolean(),
    z.null(),
    z.number(),
    z.string(),
  ]);
});

const objectSchema: z.ZodSchema<JsonObject> = z.lazy(() => {
  return z.union([z.record(valueSchema), z.array(valueSchema)]);
});

// results in a correctly typed object, or else throws an error
objectSchema.parse(JSON.parse('whatever unknown string'));

答案 1 :(得分:0)

尽管@ {Jack Wilson}扩展了Object界面确实有些讨厌,但它还是可以工作的。

interface Object {
    [index: string]: unknown; // You can't do `[index: PropertyKey]` or `[P in PropertyKey]` for some reason.
    [index: number]: unknown;
}

const ob = JSON.parse("{}") as unknown;

if (!(ob instanceof Object)) {
  throw new Error("Not an object");
}

const a = ob["foo"]; // a is unknown.