如何从对象生成带有约束的类型?

问题描述 投票:0回答:1

这是我的代码:

type t = 'a' | 'b' | 'c';

const objs = {
  obj1: { a: 1 },
  obj2: { a: 1, b: 2 },
};

// inferred type is { a: number }
objs.obj1.c; // Error

我想限制

objs
的值具有属于
t
的键。所以我重写如下:

type t = 'a' | 'b' | 'c';
type SubsetOfT = Partial<Record<t, number>>;

const objs: Record<string, SubsetOfT> = {
  obj1: { a: 1 },
  obj2: { a: 1, b: 2 },
};

// inferred type is {a?: number; b?: number; c?: number}
objs.obj1.c; // number | undefined

然后我就丢失了具体的类型信息。

type t = 'a' | 'b' | 'c';


function constrainKeys<T extends Record<string, Partial<Record<t, number>>>>(obj: T): T {
  return obj;
}

const objs = constrainKeys({
  obj1: { a: 1 },
  obj2: { a: 1, b: 2 }
});

// inferred type is { a: number }, that's good
objs.obj1.c = 1; // Error

这段代码正是我想要的。它可以正确地将 obj1 的值的类型推断为

{a: number;}
而不是
{a?: number; b?: number; c?: number}
。但有没有更简洁的写法呢?
constrainKeys
功能会降低可读性。

更新

我认为最后一个例子是正确的。但我没有注意到它根本没有约束密钥。

typescript
1个回答
0
投票

您可以使用泛型类型:

type t = 'a' | 'b' | 'c';


type ObjectRecord<K extends PropertyKey, T> = Record<string, Partial<Record<K, T>>>;

const objs: ObjectRecord<t, number> ={
  obj1: { a: 1 },
  obj2: { a: 1, b: 2 }
}

objs.obj1.c = 1; 
objs.obj1.d = 1; // Error

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.