首页 > 解决方案 > 基于输入枚举的Typescript条件返回接口

问题描述

要求是提供一个枚举数组作为参数来定义返回类型接口。基于这些枚举属性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 定义为

type Conf<E extends Key> = {
  [K in E]: K extends E[keyof E] ? FF : never;
};

返回接口中仅存在属性b,但我无法找到如何索引FF以基于 enum => 选择正确的接口B1。此外,生成的界面res.b.不是res.B.

返回接口

标签: typescriptenumsconditional-types

解决方案


这真的很棘手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]);

否则我也无法完全理解它。


推荐阅读