【问题标题】:Property does not exists on array element数组元素上不存在属性
【发布时间】:2019-04-01 12:46:53
【问题描述】:

我正在尝试返回一个包含初始化对象和数字的数组。

但是我得到以下错误:

类型 'number | 上不存在属性 'foo' IObj' 属性 'foo' 类型“数字”上不存在

interface IObj {
    [k: string]: string
}

function test(fields: string[]){
    const foo: IObj = {}
    fields.forEach((x) => foo[x] = 'baz')
    return [foo, 1]   
}
const [foo, x] = test(['foo'])
foo.foo

我该如何解决这个问题?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    默认情况下,对于数组字面量,typescript 会推断出一个数组,因此当发生解构时,每个元素都是IObj | number,第一个元素是IObj,第二个元素是数字的信息将会丢失。

    在最近发布的 3.4 中,您可以使用 as const 让编译器推断出只读元组 (return [foo, 1] as const)

    或者你可以使用显式类型注释告诉编译器你想要一个元组:

    interface IObj {
        [k: string]: string
    }
    
    function test(fields: string[]) : [IObj, number]{
        const foo: IObj = {}
        fields.forEach((x) => foo[x] = 'baz')
        return [foo, 1]  
    }
    const [foo, x] = test(['foo'])
    foo.foo
    

    如果您打算为 fields 参数使用常量,我是否可以建议您的代码使用更安全的版本:

    function test<K extends string>(fields: K[]) : [Record<K, string>, number]{
        const foo = {} as Record<K, string>
        fields.forEach((x) => foo[x] = 'baz')
        return [foo, 1]  
    }
    const [foo, x] = test(['foo'])
    foo.foo //ok
    foo.foo2 // err
    

    【讨论】:

    • 如果fields 变成IObjRecord 实现还能工作吗? (并且修改了foreach)
    • @Orelus 如果fieldsstring[],我不确定我是否理解您的问题(因为它是动态使用的)Record&lt;K, string&gt; 基本上相当于IObj
    • function test&lt;K extends string&gt;(fields: {[K: string]: string}) : [Record&lt;K, string&gt;, number] (...) 这样的东西还能用吗?还是我必须使用像test&lt;K extends string&gt;(fields: Record&lt;K, string&gt;) 这样的记录?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 2017-08-07
    相关资源
    最近更新 更多