键入可选属性的打字稿索引签名

时间:2019-07-30 14:07:28

标签: typescript

我想在打字稿3.5.3中声明这样的内容

interface User {firstName: string}
interface Contacts {[index: string]: User | undefined}

基本上,我希望打字稿警告我尝试访问的属性可能未定义的事实。目前,当我写这篇文章时不是这样:

const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId]; //typescript doesn't warn me about this being undefined

编辑:在我正在从事的特定项目中,我忘记在tsconfig中设置strict: true,而不会为user.firstName引发错误。在问题的原始状态下,答案是正确的。

1 个答案:

答案 0 :(得分:1)

通常,TypeScript仅在您执行可能无效或很可能是错误的操作时警告您。

在这种情况下,您不是。您正在读取的字段可能是未定义的,但不会立即引起错误,它是一个字典式的对象,提示这是正常的行为。

如果您执行某些绝对危险的操作,例如 use 使用该user变量并假定已定义该变量,则将收到错误消息。例如:

interface User {firstName: string}
interface Contact {[index: string]: User | undefined}

const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId];
console.log(user.firstName); // Error: Object is possibly 'undefined'

在大多数情况下,这就足够了。这样可确保任何真正使用检索到的属性的代码都必须首先确保已定义其值(例如if (user) { ... })。

如果您想在任何未知属性访问上出错,则需要删除索引签名。然后,要实际访问没有索引签名的字段,您需要向TypeScript显示该字段确实存在。有一些选项,但是例如,您可以使用a custom type guard

interface User {firstName: string}

type HasContact<N extends string> = { [name in N]: User };
function hasContact<N extends string>(x: {}, name: N): x is HasContact<N> {
    return name in x;
}

const contacts = {};
const randomId = '1240astat0252';

const user = contacts[randomId]; // Error

if (hasContact(contacts, randomId)) {
    const user = contacts[randomId]; // Inside the 'if' this is all good
    contacts['differentId']; // Still an error
}