- Published on
Prefer precise string types
- Authors
- Name
- Moch Lutfi
- @kaptenupi
String type is big and giving variable a string type will give you a lot of possibilities input values. But with the great power comes great responsibility. Suppose you're building a book collection and want to define a type for a book. Here's an attempt to define a book type:
_6interface Book {_6 title: string;_6 writer: string;_6 publishedDate: string; // YYYY-MM-DD_6 bookType: string; // hardcover, paperback, ebook_6}
That interface seems right but actually not. Here's what can go wrong:
_6const book: Book = {_6 title: 'Chemistry 12',_6 writer: 'Marthen Kanginan',_6 publishedDate: 'May 4th, 1945', // ooops, wrong format_6 bookType: 'Hardcover' // ooops again, wrong type_6};
The publishedDate
and bookType
can be narrowed down to a more precise type. For publishedDate
field it's better to use a Date
object and avoid formatting issue. Then, for the bookType field, you can define a union type with just expected values. Here's the same interface with more precise types:
_8type BookType = 'hardcover' | 'paperback' | 'ebook';_8_8interface Book {_8 title: string;_8 writer: string;_8 publishedDate: Date;_8 bookType: BookType;_8}
With these changes Typescript is able to do a more thorough validation of the data.
_7const book: Book = {_7 title: 'Chemistry 12',_7 writer: 'Marthen Kanginan',_7 publishedDate: new Date('1945-05-04'),_7 bookType: 'Hardcover'_7 // type Hardcover is not assignable to type BookType_7};
Another example misuse of string is in function parameters. Let's say you want to create simple find by bookType function. Instead using string type, you can use a union type with just expected values.
If create function with parameters that expected to be properties on an object we can use keyOf T
to narrow down the type of the parameter. For example pluck
function with generic.
_3function pluck<T, K extends keyof T>(records: T[], key: K): T[K][] {_3 return record.map(r => r[key]);_3}
Wrap up
- Avoid "stringly typed" code. Prefer more precise types where not every value is possible.
- Use union types to define more precise types.
- Prefer
keyOf
T to string for function parameters that are expected to be properties of an object.