类型“{}”不能赋值给类型“T”。

11
function f1<T extends {[prop: string]: any}}>(a: T = {}) {
    console.log(a)
}

错误:类型'{}'不能赋值给类型'T'。

我试图给一个默认值,而不是给T一个默认类型。

我不确定问题出在哪里。

1个回答

11
考虑以下例子:
type A = { [prop: string]: any };
type B = { [prop: string]: any; prop1: string };

类型B是否扩展类型A?是的!

但以下内容将不起作用。

let a: A = {};
let b: B = a; // Error

很明显,类型 A 缺少必要的属性 prop1,所以变量 a 无法赋值给变量 b

你的函数也存在相同的问题。当你执行以下操作时

function f1<T extends { [prop: string]: any }>(a: T = {}) {
    console.log(a);
}

编译器说对象{}不能分配给类型T。如果这样做可以的话,你可以这样做:
f1<B>();  // a will equal to {} and misses required prop1

这可能看起来并不像错误,因为在 f1 中你只知道 T extends { [prop: string]: any } ,并且对 prop1 一无所知。但是请考虑如果你想返回 T

function f1<T extends { [prop: string]: any }>(a: T = {}): T {
    console.log(a);
    return a;
}

如果这段代码能够正常工作的话,它将会引入一个bug。
let bb: B = f1<B>();  // Here bb will be equal to empty object
let s: string = bb.prop1;  // Compiler will not show error, as it thinks that bb has prop1 of type string. But in reality it is undefined.

所以有以下解决方案可供考虑:
  1. Remove all generics. Type { [prop: string]: any } is generic by itself so it may suit your needs

    function f1(a: { [prop: string]: any } = {}) {
        console.log(a);
        return a;
    }
    
  2. Make a fully optional. In this case a may equal to undefined and compiler would know about it.

    function f1<T extends { [prop: string]: any } = {}>(a?: T) {
        console.log(a);
    }
    

    If you return a compiler will tell you that you should either return union type (with undefined) or check in function body that a is not undefined.

  3. Worst case from my point of view is to use type cast as already suggested

    function f1<T extends { [prop: string]: any }>(a: T = {} as T) {
        console.log(a);
    }
    

    But be careful and don't forget that you can miss some required properties in this case.


我现在明白了。我之前的想法是错误的。我已经使用C#中的泛型多年了,但有时仍会对继承方向感到困惑。你说得完全正确:不能简单地将某个基本类型(在这种情况下是值 {})的值分配给(可能)派生类型(在这种情况下是 a: T)的绑定。感谢您的澄清。 - Bart Hofland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接