如何在TypeScript中键入带有索引签名和动态变量的对象?

如何在TypeScript中键入带有索引签名和动态变量的对象?,typescript,types,index-signature,Typescript,Types,Index Signature,我对TypeScript还不熟悉,并尝试了各种方法来键入它,但在索引签名方面遇到了问题。界面应该是什么样子 interface MyConfig { ... } // someVar can be any string let someVar = "dynamicKey"; // the structure of the object cannot change const config: MyConfig = { myObj: { [someVar]: {

我对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
变量的一个或多个精确值,则可以使用如下严格接口:

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())
}
在本例中,我们使用typescript索引签名+指定已知属性。您还可以注意到一件奇怪的事情-索引签名具有union
object | string
。这是因为typescript的限制:

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


参考资料:

[someVar]:
SomeKey:
相同。因此,请将其键入
SomeKey:{firstProp:string,secondProp:string}
那么您是说我的接口应该是什么样子?someVar是动态字符串吗?@zerkms无法使用您的建议,因为someVar是动态的。当我使用您的最后一个答案时,tsc编译器会说:键入“{SomeKey:{firstProp:string;secondProp:string;}”无法将“;thirdrop:string;}”分配给类型“{dynamic:{[key:string]:{firstProp:string;secondProp:string;};};};thirdrop:string;}”。Object literal只能指定已知的属性,并且类型“{dynamic:{[key:string]:{firstProp:string;secondProp:string;};};};};thirdProp:string;}”中不存在“[someVar]”。ts(2322)预期的类型来自属性“myObj”,如果您使用的是上一个示例,则该属性在类型“MyConfig”上声明,您需要更改存储数据的方式(我更新了上一个示例)。如您所见,为了便于键入,我将
[someVar]:{}
块包装为
动态。选项不起作用,因为someVar是动态的2。选项不起作用,因为我无法更改对象的结构。添加了第三个示例。这不是最好的,但它应该能起作用。我明白了,它能起作用。我将把它标为正确答案。你能给我解释一下:``[key:string]:{firstProp:string secondProp:string}string``为什么需要
\string