【问题标题】:How to type object with index signature and dynamic variable in TypeScript?如何在 TypeScript 中键入具有索引签名和动态变量的对象?
【发布时间】:2020-10-30 20:11:49
【问题描述】:

我是 TypeScript 的新手,并尝试了各种方法来键入它,但遇到了索引签名的问题。界面应该是什么样子的?

interface MyConfig {
...
}

// someVar can be any string
let someVar = "dynamicKey";

// the structure of the object cannot change
const config: MyConfig = {
  myObj: {
    [someVar]: {
      firstProp: 'some text',
      secondProp: 'some text',
    },
    thirdProp: 'some text',
  },
};


【问题讨论】:

  • [someVar]:SomeKey: 相同。所以输入为SomeKey: {firstProp: string, secondProp: string}
  • 所以你是说我的界面应该是什么样子的?
  • someVar 是动态字符串吗?
  • @zerkms 无法使用您的建议,因为 someVar 是动态的。

标签: typescript types index-signature


【解决方案1】:

如果您知道someVar 变量的确切值或值,您可以有一个严格的接口,例如:

interface MyConfig {
    myObj: {
        SomeKey: {
            firstProp: string
            secondProp: string
        },
        thirdProp: string
    }
}

那么你可以使用:

const someVar = "SomeKey";

const config: MyConfig = {
    myObj: {
        [someVar]: {
            firstProp: 'some text',
            secondProp: 'some text',
        },
        thirdProp: 'some text',
    },
};

但是如果你希望someVar 是动态的,那就有点棘手了。为此,我建议您将动态部分移至单独的块,以便您可以使用:

interface MyConfig {
    myObj: {
        dynamic: {
            [key: string]: {
                firstProp: string
                secondProp: string
            }
        },
        thirdProp: string
    }
}

const someVar = "SomeKey";
const config: MyConfig = {
    myObj: {
        dynamic: {
            [someVar]: {
                firstProp: 'some text',
                secondProp: 'some text',
            },
        },
        thirdProp: 'some text',
    },
};

最后,如果你有动态的someVar 并且不能改变数据结构。您可以使用以下内容:

interface MyConfig {
    myObj: ({
        [key: string]: {
            firstProp: string
            secondProp: string
        } | string
    } & {
        thirdProp: string
    })
}
const someVar: string = "SomeKey";

const config: MyConfig = {
    myObj: {
        [someVar]: {
            firstProp: 'some text',
            secondProp: 'some text',
        },
        thirdProp: 'some text',
    },
};

// String
console.log(config.myObj.thirdProp.trim())

// Error, union string | object
console.log(config.myObj.abc.firstProp)

if (typeof config.myObj.abc === 'object') {
    // string
    console.log(config.myObj.thirdProp.trim())
    // string
    console.log(config.myObj.abc.firstProp.trim())
}

在此示例中,我们使用打字稿索引签名 + 我们指定已知属性。您还可以注意到一个奇怪的事情 - 索引签名有 union object | string。这是因为打字稿限制:

一旦您有了字符串索引签名,所有显式成员也必须符合该索引签名。这是为了提供安全性,以便任何字符串访问都会给出相同的结果。

参考:How to combine declared interface properties with custom Index Signature

【讨论】:

  • 当我使用你的最后一个答案时,tsc 编译器说: Type '{ SomeKey: { firstProp: string; secondProp:字符串; };第三个属性:字符串; }' 不可分配给类型 '{ dynamic: { [key: string]: { firstProp: string; secondProp:字符串; }; };第三个属性:字符串; }'。对象字面量只能指定已知的属性,并且 '[someVar]' 不存在于类型 '{ dynamic: { [key: string]: { firstProp: string; secondProp:字符串; }; };第三个属性:字符串; }'.ts(2322) 预期的类型来自属性'myObj',它在'MyConfig'类型上声明
  • 如果您使用最后一个示例,则需要更改存储数据的方式(我更新了最后一个示例)。如您所见,我将[someVar]: {} 块包装到dynamic 以方便打字。
  • 两个问题:1. option 不起作用,因为 someVar 是动态的 2. option 不起作用,因为我无法更改对象的结构。
  • 添加了第三个示例。这不是最好的,但应该可以。
  • 我明白了,它正在工作。我会将其标记为正确答案。你能给我解释一下:``` [key: string]: { firstProp: string secondProp: string } |字符串```为什么需要| string
猜你喜欢
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 1970-01-01
相关资源
最近更新 更多