我有一个库,可导出类似于以下内容的实用程序类型:
type Action<Model extends object> = (data: State<Model>) => State<Model>;
此实用程序类型使您可以声明将作为“动作”执行的功能。它收到一个通用的论据,Model
即该操作将针对的论点。
data
然后使用导出的另一个实用程序类型键入“ action” 的参数。
type State<Model extends object> = Omit<Model, KeysOfType<Model, Action<any>>>;
该State
实用型基本上接受了输入Model
通用,然后创建一个新的类型,其中所有的类型的属性Action
已被删除。
例如,这是上述的基本用户土地实现;
interface MyModel {
counter: number;
increment: Action<Model>;
}
const myModel = {
counter: 0,
increment: (data) => {
data.counter; // Exists and typed as `number`
data.increment; // Does not exist, as stripped off by State utility
return data;
}
}
以上效果很好。👍
但是,在某些情况下,特别是在定义了通用模型定义时,以及在工厂函数中生成通用模型实例的过程中,我都在努力工作。
例如;
interface MyModel<T> {
value: T; // 👈 a generic property
doSomething: Action<MyModel<T>>;
}
function modelFactory<T>(value: T): MyModel<T> {
return {
value,
doSomething: data => {
data.value; // Does not exist 😭
data.doSomething; // Does not exist 👍
return data;
}
};
}
在上面的示例中,我希望在data
要doSomething
删除操作的地方键入自变量,并且通用value
属性仍然存在。但是,情况并非如此-该value
属性也已被我们的State
实用程序删除。
我相信这是因为它T
是通用的,没有对其施加任何类型限制/缩小,因此类型系统决定它与一个Action
类型相交,然后将其从data
参数类型中删除。
有办法解决这个限制吗?我已经做了一些研究,希望能有一些机制可以说明除之外的T
任何机制。即否定类型限制。Action
想像:
function modelFactory<T extends any except Action<any>>(value: T): UserDefinedModel<T> {
但是TypeScript不存在该功能。
有谁知道我可以按照预期的方式工作?
以下是完整的代码段,以帮助调试:
// Returns the keys of an object that match the given type(s)
type KeysOfType<A extends object, B> = {
[K in keyof A]-?: A[K] extends B ? K : never
}[keyof A];
// Filters out an object, removing any key/values that are of Action<any> type
type State<Model extends object> = Omit<Model, KeysOfType<Model, Action<any>>>;
// My utility function.
type Action<Model extends object> = (data: State<Model>) => State<Model>;
interface MyModel<T> {
value: T; // 👈 a generic property
doSomething: Action<MyModel<T>>;
}
function modelFactory<T>(value: T): MyModel<T> {
return {
value,
doSomething: data => {
data.value; // Does not exist 😭
data.doSomething; // Does not exist 👍
return data;
}
};
}
您可以在此处使用此代码示例:https : //codesandbox.io/s/reverent-star-m4sdb?fontsize=14