TypeScript:解释泛型函数返回值的行为



我很难理解为什么TypeScript的行为如下所示。

01| const dictionary: { [key: string]: unknown} = {}
02|
03| function set<T>(key: string, value: T): void {
04|    dictionary[key] = value;
05| }
06|
07| function get<T = unknown>(key: string): T {
08|    return dictionary[key] as T;
09| }
10|
11| set('foo', 'bar');
12|
13| const a: string = get('foo');
14|
15| const _b = get('foo');
16| const b: string = _b;

操场上联系

TS抱怨第16行,但没有第13行。

因为get函数的泛型T默认为unknown,我的预期是第13行和第16行都会引发TS错误,因为unknown不应该被赋值给string类型的变量。然而,它并没有抱怨第13行,而且,如果我将鼠标悬停在第13行的get函数上,它会说get的返回值是string而不是unknown

我已经找了几个小时来解释这种行为。我需要一些帮助。

另外,作为一个后续问题,我需要做什么改变才能让TypeScript在这两行都报错?

编辑

对不起,澄清一下。实际上,我希望TypeScript在第13行&第16行,迫使我指定泛型类型string。换句话说,我想让它强制我使用get<string>('foo')

unknown类型不能赋值给任何其他对象。因为你明确地说你将在这里得到一个字符串:

const a: string = get('foo');

typescript会认为应该将a变量强制转换为string。但是在下一行,你的get函数输出将是你提供的通用的默认值T

const _b = get('foo');

,并且因为unknown类型不能赋值给除了自身之外的任何其他类型,所以您会得到错误。

但这是你的解决方案,让它工作:

const _b = get<string>('foo');

通过这样做,您将收到字符串作为输出,并且您在下一行的变量赋值将是ok的:

const b: string = _b; // no error here

类型unkwown不能分配给任何东西,除了它自己(也许any,我没有测试)。但是,使用any作为默认类型可以解决您的问题:

01| const dictionary: { [key: string]: any } = {}
02|
03| function set<T>(key: string, value: T): void {
04|    dictionary[key] = value;
05| }
06|
07| function get<T = any>(key: string): T {
08|    return dictionary[key] as T;
09| }
10|
11| set('foo', 'bar');
12|
13| const a: string = get('foo');
14|
15| const _b = get('foo');
16| const b: string = _b;

我认为any更适合这种情况,无论如何。

最新更新