【问题标题】:TS2536:Type 'keyof T2' cannot be used to index type 'T1'TS2536:类型“keyof T2”不能用于索引类型“T1”
【发布时间】:2017-05-23 21:17:53
【问题描述】:

swagger-api/swagger-codegen 生成如下代码:

private extendObj<T1,T2>(objA: T1, objB: T2) {
    for(let key in objB){
        if(objB.hasOwnProperty(key)){
            objA[key] = objB[key];
        }
    }
    return <T1&T2>objA;
}

编译时会报错:

TS2536:类型“keyof T2”不能用于索引类型“T1”

有人可以解释为什么一个对象的密钥不能用于访问另一个对象的字段吗?密钥是否被推断为某种特殊类型?

在打字稿中复制对象属性的正确方法是什么?

【问题讨论】:

  • 如果不能保证键的类型相同,我可以看到编译器有问题。如果将 key 的类型指定为泛型会怎样?
  • 如果另一个 keyX 被声明在循环之外,它就可以工作。但这很奇怪。如果它抱怨价值,我会理解,但这是关键。

标签: typescript


【解决方案1】:

我认为正确的函数应该是like this:

function extendObj<T1,T2>(objA: T1|T2, objB: T2): T1|T2 {
    for(let key in objB){
        if(objB.hasOwnProperty(key)){
            objA[key] = objB[key];
        }
    }
    return objA;
}

返回的类型应该是 T1T2 (|) 的并集,而不是交集 (&amp;)。

也许你对keyof不熟悉,它是TypeScript 2.1的新功能。

我想编译器的推理是它知道keyT2 的有效成员但它不知道T1 这就是为什么我说objA 是@987654333 的联合@ 和 T2 (不是真的,但我想分配给 keyof T2 字段)。编译器不区分读取和写入。

我不熟悉 swagger-codegen,您是否可以控制或编辑生成的代码?

【讨论】:

  • 是的,你说得对,我没有足够认真地阅读 keyof。现在我知道了。尽管您建议的代码无法编译。这个虽然是:extendObj(objA:T2, objB: T2): T1|T2 { for(let key in objB){ if(objB.hasOwnProperty(key)){ objA[key] = objB[键]; } } 返回 objA;
  • 我在打字稿操场上编译的代码(见我的链接)
  • 和 T2 扩展 T1 在我的 Java 眼中看起来比 T1|T2 更好:)
  • 嗯,得到“错误 TS2536:类型 'keyof T2' 不能用于索引类型 'T1 | T2'。来自打字稿@2.1.4。不同的版本?
  • @user656449 extends| 具有不同的语义。看看 tinyurl “extend-with-extends”(所以我不会把链接放在这里,完整的链接太长了,无法在评论中输入)
【解决方案2】:

我已通过使用交叉类型 进行强制转换来修复它。 https://www.typescriptlang.org/docs/handbook/advanced-types.html

/** Extends objA with properties of objB and returns objA */
function extendObj<T1, T2>(objA: T1, objB: T2): T1 & T2 {
    for (let key in objB) {
        if (objB.hasOwnProperty(key)) {
            (<T1 & T2>objA)[key] = (<T1 & T2>objB)[key];
        }
    }
    return <T1 & T2>objA;
}

/** Creates an object with the specified prototype and properties coming from object (cloned) */
function fromPrototype<T, A>(prototype: T, object: A): T & A {
    // Create the object with the specified prototype
    const newObject = <T & A>Object.create(prototype);

    // Clones properties of the specified object
    for (const prop in object) {
        if (object.hasOwnProperty(prop)) {
            newObject[prop] = (<T & A>object)[prop];
        }
    }

    return newObject;
}

【讨论】:

    猜你喜欢
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    相关资源
    最近更新 更多