类的泛型方法的 TypeScript 返回类型

Mac*_*zyk 7 typescript typescript-generics

我无法获取类中泛型方法的类型,尝试这样做会导致解析错误。

class MyClass<T extends string> {
  public myMethod<U extends string>(arg: U): [T, U] {

  }
}

type returnType = ReturnType<MyClass<'test'>['myMethod']<'test'>>;
// Unexpected token. Did you mean `{'>'}` or `&gt;`?(1382)
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?

更新:我编辑了示例以避免混淆,之前未知的类型只是为了使示例简单。返回类型还取决于类泛型和方法泛型。

另外,不可能像这样隔离方法

type method = MyClass<'test'>['myMethod']

type returnType = ReturnType<method<'test'>>;
Run Code Online (Sandbox Code Playgroud)

因为method不是泛型。并将其设为通用会导致完全相同的解析错误。

Update2:<这不是返回类型的问题,而是类型本身的问题 - 不过我会保留原来的问题。我提交了一个问题

jca*_*alz 1

TypeScript 中有两种泛型;泛型类型(类实例类型、接口和类型别名)和泛型函数(泛型调用签名、方法,甚至泛型构造签名)。


泛型类型的泛型类型参数的作用域为该类型,您需要指定类型参数才能引用该类型。所以在

class MyClass<T extends string> {
  public myMethod<U extends string>(arg: U): [T, U] {

  }
}
Run Code Online (Sandbox Code Playgroud)

构造函数值的实例的类型MyClass需要有一个类型参数...您不能只将MyClass其本身编写为实例类型。你需要类似的东西MyClass<"testT">

type MyClassInstance = MyClass<"testT">;
// type MyClassInstance = MyClass<"testT">
Run Code Online (Sandbox Code Playgroud)

现在我们有了一个特定的类型。每个类型的实例MyClassInstance<"testT">都有一个myMethod方法,因此我们应该能够索引 MyClassInstance以获取该方法的类型:

type MyClassInstanceMethod = MyClassInstance["myMethod"];
// type MyClassInstanceMethod = <U extends string>(arg: U) => ["testT", U]
Run Code Online (Sandbox Code Playgroud)

在这里我们看到了另一种泛型。


该类型MyClassInstanceMethod本身不是通用的;它不需要类型参数。但该类型是泛型函数的类型,其调用签名为<U extends string>(arg: U) => ["testT", U]。泛型函数的类型参数的作用域为调用签名。您没有指定类型参数来引用该类型;类型参数通常仅在有人实际调用该类型的函数时才指定。纯粹从类型系统内部做到这一点是不可能的。

所以你不能U从 的定义中指定MyClassInstanceMethodMyClassInstanceMethod如果您尝试,您将收到非通用错误:

type Nope = MyClassInstanceMethod<"testU">; // error!
// Type 'MyClassInstanceMethod' is not generic.
Run Code Online (Sandbox Code Playgroud)

此处指定的唯一方法U是获取type 的MyClassInstanceMethod,或者至少让编译器相信您有一个值:

declare const myClassInstanceMethod: MyClassInstanceMethod; // or
// const myClassInstanceMethod = (() => { }) as Function as MyClassInstanceMethod;
Run Code Online (Sandbox Code Playgroud)

在 TypeScript 4.7 之前,继续操作的唯一方法是实际调用该函数:

const ret = myClassInstanceMethod<"testU">("testU"); // okay
// const ret: ["testT", "testU"];
Run Code Online (Sandbox Code Playgroud)

但在 TypeScript 4.7 及更高版本中,您可以使用实例化表达式来指定泛型函数的类型参数,而无需调用它:

const myClassInstanceMethodSpecified = myClassInstanceMethod<"testU">;
// const myClassInstanceMethodSpecified: (arg: "testU") => ["testT", "testU"]

type R = ReturnType<typeof myClassInstanceMethodSpecified>;
// type R = ["testT", "testU"]
Run Code Online (Sandbox Code Playgroud)

这最终就是你想要的类型。


回顾一下,指定泛型函数的类型参数的唯一方法是短暂下拉到值级别,然后可以跳回类型级别。因此这里的最少行数可能是两行:

declare const m: MyClass<'testT'>['myMethod'];
type R = ReturnType<typeof m<'testU'>>;
// type R = ["testT", "testU"]
Run Code Online (Sandbox Code Playgroud)

Playground 代码链接