只为TypeScript中的泛型类型提供某些类型

huangapple go评论67阅读模式
英文:

Providing only some types for generic type in typescript

问题

我想知道在TypeScript中是否有一种缩写方式,可以仅为泛型类型指定某些可选类型。例如,如果我有一个带有可选类型的类:

class GenericClass<A extends Type1 = Type1, B extends Type2 = Type2, C extends Type3 = Type3>

然后我想定义一个子类,如:

class Subclass extends GenericClass<TypeB>

这应该是一个缩写,相当于 class Subclass extends GenericClass<Type1, TypeB, Type3>,但是它不起作用。相反,它试图将 TypeB 推断为 Type1 的子类型,这会导致错误。然而,在这个示例中也允许省略 Type3 并让 TypeScript 推断它。类似这样的功能对于我在定义泛型 React 组件时会很有用,我想指定状态的类型,但不想指定属性的类型。

所以我想知道,是不是在指定可选类型时必须提供所有前置可选类型。还是有一种我正在尝试的方法?

对于可选函数参数,你可以简单地为前置的可选参数指定 undefined,但这对泛型不起作用,我尝试过使用 void 代替,但也不起作用。我还尝试过像 Subclass extends GenericClass<B = TypeB> 这样的语法,但也不起作用。

我见过一些建议,用接口来替换可选函数参数,例如:

interface Args { a?: number, b?: string, c?: any }
function myFunc(Args) {}

然后可以这样调用它:myFunc({ b: "value" });,而不必这样做:myFunc(undefined, "value");。这感觉像是一个不太好的替代方法,但也许对于泛型类型有类似的做法?我不太确定会是什么样子。

我尝试的另一种方法是重载类型,例如 type GenericClass<B extends Type2> = GenericClass<Type1, B, Type3>。但这不起作用,除非我给它取一个不同的名称,比如 GenericClassB

英文:

I would like to know if there is a shorthand for specifying only some optional types for generic types in typescript. For example if I have a class with optional types:

class GenericClass&lt;A extends Type1 = Type1, B extends Type2 = Type2, C extends Type3 = Type3&gt;

Then I'd like to define a subclass such as: class Subclass extends GenericClass&lt;TypeB&gt;
, which would be a shorthand for class Subclass extends GenericClass&lt;Type1, TypeB, Type3&gt;, but it doesn't work. Instead it tries to infer TypeB as a subtype of Type1 which gives an error. It is also allowed in this example, however, to leave out Type3 and let typescript infer it. Something like this would be useful for me in defining generic react components, where I want to specify the type of state, but not the props.

So am I correct that all preceding optional types must be provided when specifying an optional type. Or is there a way to do as I am trying?

For optional function arguments you can just specify undefined for the preceding optionals, this doesn't work for generics but I did try, using void instead but that also didn't work. I also tried using a syntax like Subclass extends GenericClass&lt;B = TypeB&gt; but that also doesn't work.

I've seen some suggestions for replacing optional function arguments with an interface, like:

interface Args { a?: number, b?: string, c?: any}
function myFunc(Args) {}

which can then be called like myFunc({b: &quot;value&quot;}); and avoids having to do myFunc(undefined, &quot;value&quot;);. This feels like a poor alternative, but maybe it is possible to do something like this for generic types? I'm not sure what that would look like though.

another thing I tried is overloading the type like type GenericClass&lt;B extends Type2&gt; = GenericClass&lt;Type1, B, Type3&gt;. This doesn't work, unless I type it with a different name, like GenericClassB

答案1

得分: 1

TypeScript目前没有您正在寻找的功能,至少在TS5.1版本中没有。泛型类型参数只能在它们具有默认值的情况下被省略,并且不允许跳过任何参数。有一些开放的功能请求,如果实现的话,可能会满足您的需求:

  • 有一个被请求的部分类型参数推断,详见microsoft/TypeScript#26242。这个提案的一部分将允许使用“符号”或“占位符”类型,这样您可以编写类似于 GenericClass<*, TypeB, *>GenericClass<_, TypeB, _> 等。

  • 还有一个被请求的命名类型参数,详见microsoft/TypeScript#38913,您可以编写 GenericClass<B=TypeB>,或者如microsoft/TypeScript#54254所请求的那样,您可以编写类似于 GenericClass<B: TypeB> 或可能是 GenericClass<{B: TypeB}>

  • 最后,您提到的解决方法是使用一个单一的类型参数,受限于包含所有可选属性Args类型。这个方法有效,但 TypeScript 无法从索引访问类型中推断出来;也就是说,它可以从类型为A的值中推断出A,但无法从类型为T["a"]的值中推断出T extends {a: any}。有一个开放的功能请求microsoft/TypeScript#51612可以实现这个功能,但同样地,它还不是语言的一部分。

最近提到的最后两个问题中,可能有一个或两个会被修复的希望。实际上,有一个拉取请求microsoft/TypeScript#53017正在实现最后一个问题,但我不知道它是否会被合并。(更早的一个拉取请求microsoft/TypeScript#20126也实现了这个功能,但被放弃了。)

但在那之前,您需要使用解决方法。

英文:

TypeScript doesn't currently have the feature you're looking for, at least as of TS5.1. Generic type arguments can only be omitted if they have defaults and you are not allowed to skip any. There are a few open feature requests which, if implemented, would probably do what you want:

  • There's partial type argument inference as requested in microsoft/TypeScript#26242. Part of that proposal would be to allow a "sigil" or "placeholder" type so you could write something like GenericClass&lt;*, TypeB, *&gt; or GenericClass&lt;_, TypeB, _&gt; or the like.

  • There's also named type arguments as requested in microsoft/TypeScript#38913, where you could write GenericClass&lt;B=TypeB&gt;, or as requested in microsoft/TypeScript#54254 where you could write something like GenericClass&lt;B: TypeB&gt; or maybe GenericClass&lt;{B: TypeB}&gt;.

  • Finally, the workaround you mention whereby you use a single type parameter constrained to an Args type with all optional properties works except TypeScript is unable to infer from index access types; that is, it can infer A from a value of type A, but it cannot infer T extends {a: any} from a value of type T[&quot;a&quot;]. There is an open feature request at microsoft/TypeScript#51612 which would do this, but again, it's not part of the language yet.

There might be some hope for one or both of the most recent two issues mentioned being fixed. In fact there is a pull request at microsoft/TypeScript#53017 which implements the last one, but I don't know if it will be merged. (A much older pull request at microsoft/TypeScript#20126 also implemented it, but it was abandoned.)

But until then you will need to use workarounds.

答案2

得分: 0

I'm sorry, but I can't assist with translating code snippets. If you have any other non-code related translation requests, please feel free to ask, and I'll be happy to help.

英文:

not sure how you can go about it with classes, I usually just use type and you can do this:

type Tuple3&lt;a,b,c&gt; = [a,b,c]

const t3: Tuple3&lt;number, string, string&gt; = [3, &#39;apple&#39;, &#39;banana&#39;]

type NamedTuple2&lt;a,b&gt; = Tuple3&lt;string,a,b&gt;

const namedT2: NamedTuple2&lt;number, string&gt; = [&#39;fruites&#39;, 2,...

Playground Link

huangapple
  • 本文由 发表于 2023年6月5日 05:28:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402491.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定