类型...不能分配给'从不'类型。(2322)

时间:2020-05-12 17:44:53

标签: typescript

以下代码段在Type 'string' is not assignable to type 'never'.(2322)行中报告了一个错误obj[prop] = value,我很难理解为什么?

interface fooType {
    s: string,
    n: number,
}

function bar(value: string, obj: fooType, prop: keyof fooType) {
    if (typeof value === 'string') {
        obj[prop] = value;
    }
}

const foo = {s: '', n: 0};

bar('s', foo, 's');

console.log(foo);

3 个答案:

答案 0 :(得分:2)

fooType['s']是类型stringfooType['n']是类型编号,所以obj[prop]是类型string & number,因为它是可分配给obj[prop]的唯一类型。并且string & number = never

答案 1 :(得分:2)

prop: keyof fooType表示prop可以为"s""n"。但是,这两个属性值具有不兼容的类型。因此,打字稿尝试通过找到属性.s .n的类型的交集来推断可分配给这两个值的值。确实如此:string & number,它们没有重叠,所以类型为never

如果要将参数作为联合(例如"s" | "n")输入 ,则需要知道该联合的哪个成员,则需要泛型。

对于通用参数,这里至少需要两个。一个用于您想要更新的属性名称(我们将使用K作为键),另一个用于值以确保其与属性的类型匹配(我们将使用V作为值)

您现在可以删除typeof value === 'string',因为打字稿将确保该值是该属性的正确类型。

function bar<
    K extends keyof fooType,
    V extends fooType[K]
>(
    value: V,
    obj: fooType,
    prop: K
) {
    obj[prop] = value;
}

const foo = {s: '', n: 0};

bar('string', foo, 's'); // works
bar(123, foo, 'n'); // works


// Should be type errors:
bar('string', foo, 'n') // '"string"' is not assignable to parameter of type 'number'
bar(123, foo, 's') // '123' is not assignable to parameter of type 'string'.

答案 2 :(得分:1)

您需要在此处使用泛型,然后它才能正确匹配类型。

interface fooType {
    s: string,
    n: number,
}

function bar<
  OBJ extends fooType,
  KEY extends keyof OBJ,
  VAL extends OBJ[KEY]
>(value: VAL, obj: OBJ, prop: KEY) {
  obj[prop] = value;
}

const foo = {s: '', n: 0};

bar('s', foo, 's');

console.log(foo);