【发布时间】:2022-06-10 22:41:50
【问题描述】:
我正在尝试编写一个工具来生成具有类型安全调用的 API 客户端,添加将负责验证输入并将其整理出来的库。
我想实现一个全局转换选项,以允许用户根据给定的类型修改响应。
假设我们有一组共享一个 Base 的类型,即
type Base<NAME extends string, T> = {
name: NAME;
value: T;
}
// All the possible responses given to the API
type ALL = Base<'Animal', Animal> | Base<'ZooKeeper', ZooKeeper> | Base<'Visitor', Visitor>;
我想编写一个函数来将所有Animal 转换为TaggedAnimal 和ZooKeeper 转换为Keeper 即
const transformer = (value: ALL) => {
if (value.name === 'Animal') {
return {
name: 'TaggedAnimal',
value: {
...value.value,
tag: 'mytag' // or something else made up of animal attributes
}
} as Base<'TaggedAnimal', TaggedAnimal>;
} else if (value.name === 'ZooKeeper') {
return {
name: 'Keeper',
value: {
id: value.value.id
}
} as Base<'Keeper', Keeper>;
}
return value;
}
到目前为止一切都很好,但是当我尝试在特定 API 上使用此函数时,问题就出现了。
const getAnimal = (): Base<'Animal', Animal> => {
// do network request, validation, etc
return {
name: 'Animal',
value: {
id: '123',
name: 'Lion'
}
} as Base<'Animal', Animal>;
}
const animal = getAnimal(); // Good! type of animal: Base<'Animal', Animal>
const tanimal = transformer(animal); // :/! type of tanimal: Base<'TaggedAnimal', TaggedAnimal> | Base<'Keeper', Keeper> | Base<'Visitor', Visitor>;
我知道这是因为 transformer 需要所有类型并返回一个固定子集(由函数给出)。
当前版本的 typescript (4.7) 有什么方法可以解决这个问题吗?
我曾尝试使用泛型来缩小范围,即:
const transformer = <IN extends ALL>(value: IN) => {
// ...
}
const tanimal = transformer(animal); // :/! type of tanimal: Base<'Animal', Animal> | Base<'TaggedAnimal', TaggedAnimal> | Base<'Keeper', Keeper>;
【问题讨论】:
标签: typescript