对于对象键中的条件类型,如何删除某些键以生成子集对象类型?



这是我使用一些高级类型的方式。我想创建一个扩展 BaseConfig 的配置类型。使用此配置类型,inter 到 dataProducer 类型(在示例中命名为 Conf(,该类型具有在配置类型中标记为"yes"的相同属性。

interface BaseConfig1 {
a: 'yes'|'no';
b: 'yes'|'no';
}
interface BaseConfig2 {
a?: 'yes';
b?: 'yes';
}
interface Config1 extends BaseConfig1 {
a: 'yes';
}
interface Config2 extends BaseConfig2 {
a: 'yes';
}

type Conf<T, D> = {
[P in keyof T]: T[P] extends 'yes'? ((data:D) => string): never;
};
// Error. Missing property b.
const dataProducer1: Conf<Config1, any> = {a: (data:any) => ''};
// Works
const dataProducer2: Conf<Config2, any> = {a: (data:any) => ''};

理想情况下,BaseConfig1是我真正想要定义的。您需要在子类型中标记"是"以配置输出类型。但是 TS 坚持让我提供一个类型为 never 的 b 属性。不是不应该像过滤器类型一样被排除在类型之外吗?type Filter<T, U> = T extends U ? T : never;

我能做的最好的事情就是 BaseConfig2,有什么更好的主意吗?

更新:我确实想强制结果类型将属性标记为"是"类型。对于上面的示例,结果类型应具有"a"属性。

更新2:另一个问题,对于BaseConfig2,b的类型是'yes'|undefined,那么为什么Conf<Config2, any>会期望一个具有未定义类型的可选b属性而不是具有从不类型的b。

更新3:尝试了另一种方法来定义Conf,但不起作用。

type Conf<T, D> = {
[P in keyof T & T[P] extends 'yes']: (data:D) => string;
};
interface BaseConfig {
a: 'yes'|'no';
b: 'yes'|'no';
}
interface BaseConfigD {
a: (data:any) => string;
b: (data:any) => string;
}
interface Config extends BaseConfig {
a: 'yes';
}
// Extract the property names that extend 'yes'
type ConfProps<T> = {
[P in keyof T]: T[P] extends 'yes'? P: never;
}[keyof T];
// Properties of Config that extend 'yes'
type ConfigProps = ConfProps<Config>;
// Properties of BaseConfigD that extend 'yes' from Config..
type BaseConfigDBasedOnConfigProps = Pick<BaseConfigD, ConfigProps>;
const dataProducer1: BaseConfigDBasedOnConfigProps = {a: (data:any) => ''};

最新更新