【问题标题】:Type constraint between methods方法之间的类型约束
【发布时间】:2018-11-27 21:06:39
【问题描述】:

是否可以在方法之间创建具有类型约束的类/对象?

abstract class Test<T>{
  abstract method1(): T
  abstract method2 (arg: T):any
}

我想要的是 method2 的参数与 method1 的返回类型相同 - 如果类型不同,我应该得到一个类型错误。类型本身并不重要。

我通过使用泛型类实现了这一点,但是我需要提前传入类型,这对我来说似乎是人为的和不必要的。

  1. 有没有办法做到这一点,而无需提前指定类型,或者没有泛型类?
  2. 附带问题 - 是否可以引用其他方法的类和/或返回类型? method2(arg: ReturnType&lt;this.method1&gt;):anymethod2(arg: typeof this.method1):any 中的内容?

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    解决方案

    使用ReturnType&lt;Test['method1']&gt; 代替ReturnType&lt;this.method1&gt;

    class RandomClass{
      methodX(): number {
        return 1;
      }
    }
    
    let randomFunction = function() : boolean {
      return true;
    }
    
    class TestClass{
      method1(): string {
        return '';
      };
      method2 (arg: ReturnType<TestClass['method1']>): any {
        return null;
      }
      method3 (arg: ReturnType<RandomClass['methodX']>): any {
        return null;
      }
      method4 (arg: ReturnType<typeof randomFunction>): any {
        return null;
      }
    }
    
    let test = new TestClass();
    
    test.method2('asd'); // OK
    test.method2(2); // TS compilation error. Expected string
    
    test.method3(5); // OK
    test.method3('asdf'); // TS compilation error. Expected number
    
    test.method4(true); // OK
    test.method4('asd'); // TS compilation error. Expected boolean
    

    检查此代码与stackblitz 中的 TS 错误。

    注意:ReturnType&lt;&gt; 从 TypeScript 2.8+ 开始有效。

    【讨论】:

    • 感谢您的回答。这接近我想要的,但这种情况可能吗?要拥有一个抽象基类,需要任何其他扩展基类的类来实现方法1 和方法2。并且以某种方式在 Base 类中,将 method1 的返回类型和 method2 的参数类型“链接”在一起。每个子类可以用不同的类型以不同的方式实现method1和method2,但是method1和method2之间的“类型链接”必须始终填满。
    • Mako,恐怕你做不到。当您将方法标记为abstract 时,您需要在派生类中实现它,并且当您这样做时,您将覆盖abstract 方法中的任何返回类型。在这种情况下,解决方案是实现我在每个派生类中的建议。
    【解决方案2】:

    我假设您希望能够为任意 T 定义链接的函数对,否则您只需编写具有具体类型的函数,对吗?我认为无论以何种方式分割它,都需要一个泛型类型参数,以将第一个函数的返回类型与第二个函数的参数联系起来。

    怎么样:

    interface Linked<T> {
        (): T;
        method2: (arg: T) => any;
    }
    
    const method1String: Linked<string> = () => "foo";
    method1String.method2 = arg => arg.length;
    

    试一试,这有两个不错的属性:

    • 如果您没有 method2 属性,则会出现编译器错误。
    • method2 的参数类型已正确推断,如果您尝试以其他方式键入,则会出现编译器错误。

    也就是说,我认为了解这里的上下文会很有用。据推测,这些功能旨在以某种方式一起使用,那么是什么阻止您以这种方式简单地限制它们呢?

    function doSomethingWithLinkedFunctions<T>(function1: () => T, function2: (arg: T) => any) {
    }
    

    这样做的好处是不需要一些笨拙的数据类型,并且能够从function1 推断出T

    另一种选择,以防这对功能需要保持在一起:

    type Linked<T> = [() => T, (arg: T) => any];
    
    function doSomething([func1, func2]: Linked<string>) {
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多