Reputation: 619
I would like to declare something like this in typescript 3.5.3
interface User {firstName: string}
interface Contacts {[index: string]: User | undefined}
Basically I would like typescript to warn me about the fact that the property I am trying to access is potentially undefined. Currently, that's not the case when I write this:
const contacts: Contact = {};
const randomId = '1240astat0252';
const user = contacts[randomId]; //typescript doesn't warn me about this being undefined
edit: in the specific project I was working on I forgot to set strict: true
in the tsconfig which would not raise an error for user.firstName
. In the original state of the question, the answer is correct.
Upvotes: 3
Views: 7763
Reputation: 13286
In general, TypeScript will only warn you when you're doing something that's potentially invalid or very likely to be a mistake.
In this case, you're not. You're reading a field that may be undefined, but that won't immediately cause an error, and it's a dictionary-style object which suggests that's normal behaviour.
If you do do something that's definitely dangerous, such as use that user
variable and assume that it is defined, then you'll get an error. For example:
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'
For most cases, that's enough. This ensures that any code that really uses retrieved properties must first ensure their value is defined (e.g. if (user) { ... }
).
If you want an error on any unknown property accesses, you need to remove the index signature. To then actually access fields with no index signature, you'll need to show TypeScript that the field definitely exists. There's a few options, but as an example you could use 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
}
Upvotes: 4