问题描述
要求是提供一个枚举数组作为参数来定义返回类型接口。基于这些枚举属性Key.A
和或Key.B
,返回类型接口应包含带有属性键(如枚举键)A1
和或的B1
和或A
B
。
预设置如下:
import { parse } from 'someWhere'; \\ will capitalize config first-lvl attributes
enum Key {
A = "a",B = "b",}
interface A1 {
x: string;
}
interface B1 {
y: string;
}
type FF = {
A: A1;
B: B1;
};
type Conf = <???>???;
const Fn = <E extends Key>(key: E[],config: unkNown): Conf<E> => {
return parse.JSON(key,config) as Conf<E>;
};
结果应该是使用某些枚举值调用Fn
,并且返回的接口仅包含相应的属性,例如:
const config = '{ "b": { "y": "some string" } }';
const res = Fn([Key.B],config);
console.log(res.B.y) // 'some string'
console.log(res.A.x) // Type Error: Property 'A' does not exist on type
基于此,我尝试了以下操作:
type Conf<E extends Key> = {
[K in keyof typeof Key]: K extends E[keyof E] ? FF[K] : never;
};
const res = Fn([Key.B]);
通过此实现,Key的所有属性都存在于res
中:
第二种方法是定义Conf like
type Conf<E extends Key> = {
[K in E]: K extends E[keyof E] ? FF : never;
};
返回接口中仅存在属性b
,但我无法根据索引=> FF
找出如何对B1
进行索引以选择正确的接口。另外,生成的接口是res.b.
而不是res.B.
解决方法
这确实很棘手,因为Key.B
,"B"
和"b"
都不同。
如果您愿意重写地图FF
,使其以实际的枚举值"a"
和"b"
(而不是枚举属性名称)作为键,则它变得非常简单。您可以只使用Pick<FF,E>
来获取返回类型。
type FF = {
a: A1;
b: B1;
};
const fn = <E extends Key>(key: E[],config?: unknown): Pick<FF,E> => {
return parse.JSON(key,config) as Pick<FF,E>;
};
const res1: {b: B1} = fn([Key.B]);
const res2: {a: A1} = fn([Key.A]);
const res3: {a: A1,b: B1} = fn([Key.A,Key.B]);
否则我也不太明白。