Typescript 摘要 属性 没有获取函数参数类型
Typescript abstract property not getting function arg types
我正在尝试创建一个通用抽象 class 以便能够传入一个类型以强制开发人员实现传入的类型。但是由于某种原因,函数的参数被键入除非我在扩展摘要的 class 中进一步键入 属性。
下面是我想要实现的目标的 classes。
在 Generic1 中,参数都是任何类型,但 return 类型是正确的。
在 Generic2 中,参数是正确的类型以及 return 类型,但需要再次添加控件 属性 的类型才能使其正常工作。
我错过了什么吗?我更喜欢使用 Generic1,但不确定是否可行。
declare type Signiture<L> = {
[E in keyof L]: [any, any?];
};
declare type ControlSignature<L extends Signiture<L>> = {
[E in keyof L]: (params: L[E][0]) => Promise<L[E][1]>;
};
abstract class Abstract<
C extends Signiture<C> = {[messageName: string]: [any, any?] | [void, any?]}
> {
protected abstract control: ControlSignature<C>;
}
interface X {
test1: [{ hello: string }, { world: string }],
test2: [{ nothing: number }, { something: number }],
}
class Generic1 extends Abstract<X> {
control = {
test1: async (params) => {
return { world: "test" }
},
test2: async (params) => {
return { something: 1 }
}
}
}
class Generic2 extends Abstract<X> {
control: ControlSignature<X> = {
test1: async (params) => {
return { world: "test" }
},
test2: async (params) => {
return { something: 1 }
}
}
}
不幸的是,这是 TypeScript 的设计限制,至少从 TS 4.0 开始是这样。
目前,未明确注释的子类的初始化属性被推断为具有初始化值的类型,而不关注超类。
有一个悬而未决的问题(此时相当古老),microsoft/TypeScript#10570,跟踪从其超类继承初始化属性类型的建议。您可能想转到上面的问题并给它一个记录您希望它发生的愿望,但我怀疑它是否会产生很大的影响。
似乎人们普遍对当前的行为不满意。但是之前解决这个问题的尝试 microsoft/TypeScript#6118 and microsoft/TypeScript#10610 失败了,因为它们要么在常见用例中给出了奇怪的结果(例如,使用上下文类型),要么因为它们破坏了 real-world 依赖的代码 当前行为。
由于要求希望当前缩小行为的用户明确注释其子属性将是一项重大更改,因此尚不清楚如何推进。通常避免重大更改,除非它们具有绝对明显的好处,这些好处超过修复依赖于 TypeScript 的真实代码库的努力。有许多 TypeScript 功能可以说是“以错误的方式”实现的,但它们还没有严重到足以破坏当前用户的稳定;如果你有一台空闲时间机器并且不想尝试防止各种历史灾难,你可以改为修复这些。
在当前的时间线中,可能很难证明值得打破依赖属性获取初始化器类型的现有代码,因为自己注释 属性 的变通方法很容易做。
所以现在我想说的是自己注释属性并继续。
我正在尝试创建一个通用抽象 class 以便能够传入一个类型以强制开发人员实现传入的类型。但是由于某种原因,函数的参数被键入除非我在扩展摘要的 class 中进一步键入 属性。
下面是我想要实现的目标的 classes。
在 Generic1 中,参数都是任何类型,但 return 类型是正确的。
在 Generic2 中,参数是正确的类型以及 return 类型,但需要再次添加控件 属性 的类型才能使其正常工作。
我错过了什么吗?我更喜欢使用 Generic1,但不确定是否可行。
declare type Signiture<L> = {
[E in keyof L]: [any, any?];
};
declare type ControlSignature<L extends Signiture<L>> = {
[E in keyof L]: (params: L[E][0]) => Promise<L[E][1]>;
};
abstract class Abstract<
C extends Signiture<C> = {[messageName: string]: [any, any?] | [void, any?]}
> {
protected abstract control: ControlSignature<C>;
}
interface X {
test1: [{ hello: string }, { world: string }],
test2: [{ nothing: number }, { something: number }],
}
class Generic1 extends Abstract<X> {
control = {
test1: async (params) => {
return { world: "test" }
},
test2: async (params) => {
return { something: 1 }
}
}
}
class Generic2 extends Abstract<X> {
control: ControlSignature<X> = {
test1: async (params) => {
return { world: "test" }
},
test2: async (params) => {
return { something: 1 }
}
}
}
不幸的是,这是 TypeScript 的设计限制,至少从 TS 4.0 开始是这样。
目前,未明确注释的子类的初始化属性被推断为具有初始化值的类型,而不关注超类。
有一个悬而未决的问题(此时相当古老),microsoft/TypeScript#10570,跟踪从其超类继承初始化属性类型的建议。您可能想转到上面的问题并给它一个记录您希望它发生的愿望,但我怀疑它是否会产生很大的影响。
似乎人们普遍对当前的行为不满意。但是之前解决这个问题的尝试 microsoft/TypeScript#6118 and microsoft/TypeScript#10610 失败了,因为它们要么在常见用例中给出了奇怪的结果(例如,使用上下文类型),要么因为它们破坏了 real-world 依赖的代码 当前行为。
由于要求希望当前缩小行为的用户明确注释其子属性将是一项重大更改,因此尚不清楚如何推进。通常避免重大更改,除非它们具有绝对明显的好处,这些好处超过修复依赖于 TypeScript 的真实代码库的努力。有许多 TypeScript 功能可以说是“以错误的方式”实现的,但它们还没有严重到足以破坏当前用户的稳定;如果你有一台空闲时间机器并且不想尝试防止各种历史灾难,你可以改为修复这些。
在当前的时间线中,可能很难证明值得打破依赖属性获取初始化器类型的现有代码,因为自己注释 属性 的变通方法很容易做。
所以现在我想说的是自己注释属性并继续。