
/** * p_value 这个属性用户不感知 */ abstract class A<T, P> { protected p_value: P; protected t_value: T; } /** * B 和 C 是 A 的子类,虽然 p_value 类型不一样但是存在这一属性 */ class B<T> extends A<T, number> {} class C<T> extends A<T, string> {} /** * 用户在 doSomething 的时候需要类型抽象,但是 p_value 不确定,是不感知的 */ function doSomeThing(objA: A<number, unknown>, objB: A<number, unknown>) {} /** * 例如 b 和 c 都是 number 类型 */ const b = new B<number>(); const c = new C<number>(); doSomeThing(b, c); /** * 问:有没有办法优化这个架构,让 A 自动推断 P 类型 */ 1 shigella 2022 年 8 月 10 日 emmm 范型 P 定义在 A (因为 A 内需要 P 的类型才能完成具体实现),这个 P 一定需要由外部传递。那就两条路可以传入 1. 从派生类的类型定义声明具体 P 类型,子类不再对 P 类型参数继续扩展。扩展通过更多的子类实现,你需要在 A 内完成针对 P 的所有通用的抽象实现; 2. 继续将 P 作为范型参数(为了继续扩展或派生类 BC 需要 P 的类型去完成具体实现),由 new 的时候传入。子类的目的是为了针对特定类型的 P 完成具体实现。 |
2 shigella 2022 年 8 月 10 日 有点问题修正一下…… 范型 P 定义在 A (因为 A 内需要 P 的类型才能完成具体实现),这个 P 一定需要由外部传递。那就两条路可以传入 1. 从派生类 BC 的类型定义声明具体 P 类型,孙类不再对 P 类型参数继续扩展。扩展通过更多 A 的子类达成,你需要在 A 内完成针对 P 的所有通用的抽象实现; 2. 继续将 P 作为范型参数(为了能够在孙类继续扩展针对 P 的逻辑 或 子类 BC 需要 P 的类型去完成具体实现),由 new 的时候传入。子类 BC 的目的是为了针对特定类型的 P 完成具体实现。如果不是出于这个目的就没必要选这条路。 |
3 shigella 2022 年 8 月 10 日 如果你不需要 P 的类型去实现逻辑,确实直接就 object 就完事了。 但是在 A 里面定义范型参数 P ,那说明一定是依赖的 P 的类型去干活了 这个依赖可以是因为内部反射,或者针对不同类型要 switch case ,或者是需要提供范型的返回值类型诸如此类。 |