如何使用自动推断创建嵌套泛型类型



假设我想创建一个" feature-config ",它的类型如下:

type FeatureConfig = {
isActivated: boolean;
childs?: {
[key: string]: FeatureConfig;
}
}
const config : FeatureConfig = {
isActivated: true,
childs: {
bar: {
isActivated: true,
childs: {
foo: {
isActivated: true
}
}
},
foo: {
isActivated: false,
childs: {
bar: {
isActivated: true
}
}
}
}
}

到目前为止都很好,已经检查过了。现在我想创建一个"构建"函数,它接受一个Config并返回一个"特征树"。我可以检查某个功能是否被激活。我使用该函数的目标是具有以下语法/功能:

/// How should the types of this function look like??
const createFeatureChecker = (config: FeatureConfig) => {
//...implementation
}
const featureChecker = createFeatureChecker(config);
featureChecker.bar.foo.isActivated // true
featureChecker.foo.isActivated // false
featureChecker.foo.bar.isActivated // false (since featureChecker.foo.isActivated is false)

我在普通的旧javascript中实现函数逻辑没有问题,但我正在努力以某种方式键入createFeatureChecker,以便我可以以类型安全的方式使用featureChecker

关于如何解决我的问题有什么想法吗?

您需要使用as const声明config或将其作为对象文字传递。

const config = {
isActivated: true,
childs: {
bar: {
isActivated: true,
childs: {
foo: {
isActivated: true
}
}
},
foo: {
isActivated: false,
childs: {
bar: {
isActivated: true
}
}
}
}
} as const

一个类型的createFeatureFunction看起来像这样:

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
type CreateFeatureChecker<T extends FeatureConfig, Activated extends boolean = true> = {
isActivated: Activated extends true ? T["isActivated"] : false
} & {
-readonly [K in keyof (T["childs"])]: 
(T["isActivated"] extends false ? false : Activated extends false ? false : true) extends infer A extends boolean
? T["childs"][K] extends { isActivated: infer B extends boolean } 
? T["childs"][K] extends { childs: infer C extends {
[key: string]: FeatureConfig;
}} 
? Expand<CreateFeatureChecker<{ isActivated: B, childs: C }, A>>
: Expand<CreateFeatureChecker<{ isActivated: B }, A>>
: never
: never
}
const createFeatureChecker = <T extends FeatureConfig>(config: T): Expand<CreateFeatureChecker<T>> => {
return {} as any
}

一些测试,看看它是否工作:

const featureChecker = createFeatureChecker(config);
const a = featureChecker.bar.foo.isActivated // true
const b = featureChecker.foo.isActivated // false
const c = featureChecker.foo.bar.isActivated // false

游乐场

最新更新