默认泛型可以按预期方式作为参数工作,但不能作为函数参数的返回类型工作

时间:2019-11-13 22:48:15

标签: typescript generics typescript-generics

我设法对类型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),如您在最后一行看到的那样,它会按预期工作,但是这违背了首先使用泛型的目的。

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

1 个答案:

答案 0 :(得分:3)

我一直在调查您的问题,据我所知,它应该可以那样工作。

如果查看您的d()函数的类型,则您有一个InferredType extends T

在第16-18行上,T作为B传递。当您尝试将T作为Ad<A>(() => ({ bar: 'bar', ping: 'ping' }));)传递时,将触发错误消息,提示需要foo

所以我认为您的InferredType在扩展您的{ ping?: string}类型时被解释为T。您可以继续进行以下操作:d<B>(() => ({ bar: 'bar', ping: 'ping', pong: 'pong', hello: 'hello' }));。只要定义了bar,就不会出错。

不要犹豫,问是否不够清楚!