Inspecting TypeScript's inferred types
Here’s an assertion from the TypeScript handbook: “TypeScript knows the JavaScript language and will generate types for you in many cases.”
Reading between the lines, these two lines of code, one explicitly typed and one not, should be equivalent.
let greeting: string = 'hello';let greeting = 'hello';We can assume the second example should be implicitly typed as a string
because TypeScript “knows.” The handbook sometimes refers to this as “Contextual
typing.”
But what’s going on under the hood? One way to answer that question is by emitting the type declaration. Consider this file with no explicit typing:
let greeting = 'hello';const fullName = (first: string, last: string) => first + ' ' + last;const answer = 42;We run it through the tsc compiler with the --declaration and
--emitDeclarationOnly flags— output the declaration, and only the
declaration):
npx tsc implicitlyTyped.ts --declaration --emitDeclarationOnlyWhich produces this:
declare let greeting: string;declare const fullName: (first: string, last: string) => string;declare const answer = 42;There are a couple of neat things going on here:
- We used
let, sogreetingcan be re-assigned. TypeScript typed it as astring. fullNameconcatenates two strings, so TypeScript determined thatfullNamemust return a string, and typed it.answeris a constantconst, so TypeScript used a42number literal.
The last example is instructive. With const, TypeScript can infer a literal
type (42) instead of the wider number. That’s one more argument in favor of
(almost) always using const: tighter inferred types.
There are at least two more methods for inspecting these types that will be familiar to most TypeScript devs. The first is hovering on a variable in your TypeScript-server-enabled text editor. The second is throwing a type error and reasoning through it.
- Types by Inference — TypeScript Handbook
- Declaration Reference — TypeScript Handbook