基于输入枚举的 Typescript 条件 return 接口
Typescript conditional return interface based on input enums
要求是提供一个枚举数组作为定义 return 类型接口的参数。基于这些枚举属性 Key.A
和或 Key.B
return 类型接口应包含 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
被一些枚举值调用并且 returned 接口只包含相应的属性,如:
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
:
Return Interface
第二种方法是像这样定义 Conf
type Conf<E extends Key> = {
[K in E]: K extends E[keyof E] ? FF : never;
};
只有属性 b
存在于 return 接口中,但我找不到如何根据枚举将 FF
索引到 select 正确的接口 => B1
。此外,生成的界面是 res.b.
而不是 res.B.
Return Interface
这真的很棘手,因为 Key.B
、"B"
和 "b"
都是不同的。
如果您愿意重写您的地图 FF
,使其以实际枚举值 "a"
和 "b"
而不是枚举 属性 名称作为键,它变得非常简单。您可以只使用 Pick<FF, E>
来获取 return 类型。
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]);
不然我也不太明白
要求是提供一个枚举数组作为定义 return 类型接口的参数。基于这些枚举属性 Key.A
和或 Key.B
return 类型接口应包含 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
被一些枚举值调用并且 returned 接口只包含相应的属性,如:
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
:
Return Interface
第二种方法是像这样定义 Conf
type Conf<E extends Key> = {
[K in E]: K extends E[keyof E] ? FF : never;
};
只有属性 b
存在于 return 接口中,但我找不到如何根据枚举将 FF
索引到 select 正确的接口 => B1
。此外,生成的界面是 res.b.
而不是 res.B.
Return Interface
这真的很棘手,因为 Key.B
、"B"
和 "b"
都是不同的。
如果您愿意重写您的地图 FF
,使其以实际枚举值 "a"
和 "b"
而不是枚举 属性 名称作为键,它变得非常简单。您可以只使用 Pick<FF, E>
来获取 return 类型。
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]);
不然我也不太明白