2

我是 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',
  },
};


4

1 回答 1

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。这是因为打字稿限制:

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

参考:如何将声明的接口属性与自定义索引签名相结合

于 2020-10-29T08:45:21.540 回答