【问题标题】:Default generic works as expected as parameter but not as a return type for a function parameter默认泛型可按预期作为参数工作,但不能作为函数参数的返回类型
【发布时间】:2020-03-09 19:45:44
【问题描述】:

我已经设法为我的 A 类型的泛型使用默认值,并且在将其用作对象参数(函数 c)时效果很好,但是如果我尝试将其用作传入函数参数的返回类型(函数 d) 它没有正确地与Object literal may only specify known properties, and 'ping' does not exist in type 'B'. 出错

type A = { foo: string }
type B = { bar: string }

function c<T = A, InferredType extends T = T>(config: InferredType): void { }
function d<T = A, InferredType extends T = T>(config: () => InferredType): void { }

c({ foo: 'foo' });
c({ bar: 'bar' }); // Correctly errors
c<A>({ bar: 'bar' }); // Correctly errors
c<B>({ bar: 'bar' });
c<B>({ bar: 'bar', ping: 'ping' }); // Correctly errors

d(() => ({ foo: 'foo' }));
d(() => ({ bar: 'bar' })); // Correctly errors
d<A>(() => ({ bar: 'bar' })); // Correctly errors
d<B>(() => ({ bar: 'bar' }));
d<B>(() => ({ bar: 'bar', ping: 'ping' })); // Should error with unknown property but doesn't
d<B>((): B => ({ bar: 'bar', ping: 'ping' })); // Errors correctly but requires duplicate type

Playground Link

如果我再次指定类型 (B),正如您在最后一行看到的那样,它会按预期工作,但这首先破坏了使用泛型的目的。

这是打字稿本身的问题还是我在这里遗漏了什么?

【问题讨论】:

  • answer 有帮助吗?
  • 这与超额财产检查的工作方式有关。 d&lt;B&gt;(() =&gt; ({ bar: 'bar', ping: 'ping' })) 编译,因为内部回调的返回类型只是预期在结构上可分配给 B 作为类型参数 InferredType 的实例化。给定的对象字面量不需要完全匹配B:您没有用B 明确地注释内部回调返回类型,因此在内部函数上下文中推断对象类型。
  • 或者换一种说法,为了让多余的属性检查起作用,您必须“立即”在上下文中键入对象字面量 - 就像在上一个示例中一样,会发出错误。
  • 谢谢@ford04。这个答案确实有帮助。很遗憾,除非我错过了什么,否则我不能通过泛型强制进行这种“新鲜”检查。我的用例是在现有代码库中强制执行选择器生成的特定定义。我可能不得不通过 tslint 裁决来处理这个问题。感谢您的帮助。

标签: typescript generics typescript-generics


【解决方案1】:

我一直在调查您的问题,据我了解,它应该是这样工作的。

如果您查看 d() 函数的类型,您会发现 InferredType extends T

在第 16-18 行,TB 的形式传递。当您尝试将T 作为A (d&lt;A&gt;(() =&gt; ({ bar: 'bar', ping: 'ping' }));) 传递时,它会触发一个错误,指出foo 是必需的。

所以我认为您的 InferredType 被解释为 { ping?: string},因为它扩展了您的 T 类型。您可以继续使用,例如:d&lt;B&gt;(() =&gt; ({ bar: 'bar', ping: 'ping', pong: 'pong', hello: 'hello' }));。只要定义了bar,就没有错误。

不够清楚的不要犹豫!

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多