Item 18: Avoid Cluttering Your Code with Inferable Types
Avoid writing type annotations when TypeScript can infer the same type.
Ideal TypeScript code has type annotations in function/method signatures but not on local variables in their bodies.
Consider using explicit annotations for object literals to enable excess property checking and ensure errors are reported close to where they occur.
Don't annotate function return types unless the function has multiple returns, is part of a public API, or you want it to return a named type.
💻 playground
💻 playground
const person : {
name : string ;
born : {
where : string ;
when : string ;
} ;
died : {
where : string ;
when : string ;
}
} = {
name : 'Sojourner Truth' ,
born : {
where : 'Swartekill, NY' ,
when : 'c.1797' ,
} ,
died : {
where : 'Battle Creek, MI' ,
when : 'Nov. 26, 1883'
}
} ;
💻 playground
const person = {
name : 'Sojourner Truth' ,
born : {
where : 'Swartekill, NY' ,
when : 'c.1797' ,
} ,
died : {
where : 'Battle Creek, MI' ,
when : 'Nov. 26, 1883'
}
} ;
💻 playground
function square ( nums : number [ ] ) {
return nums . map ( x => x * x ) ;
}
const squares = square ( [ 1 , 2 , 3 , 4 ] ) ;
// ^? const squares: number[]
💻 playground
const axis1 : string = 'x' ;
// ^? const axis1: string
const axis2 = 'y' ;
// ^? const axis2: "y"
💻 playground
interface Product {
id : number ;
name : string ;
price : number ;
}
function logProduct ( product : Product ) {
const id : number = product . id ;
const name : string = product . name ;
const price : number = product . price ;
console . log ( id , name , price ) ;
}
💻 playground
interface Product {
id : string ;
name : string ;
price : number ;
}
💻 playground
function logProduct ( product : Product ) {
const id : number = product . id ;
// ~~ Type 'string' is not assignable to type 'number'
const name : string = product . name ;
const price : number = product . price ;
console . log ( id , name , price ) ;
}
💻 playground
function logProduct ( product : Product ) {
const { id, name, price} = product ;
console . log ( id , name , price ) ;
}
💻 playground
function logProduct ( product : Product ) {
const { id, name, price} : { id : string ; name : string ; price : number } = product ;
console . log ( id , name , price ) ;
}
💻 playground
function parseNumber ( str : string , base = 10 ) {
// ^? (parameter) base: number
// ...
}
💻 playground
// Don't do this:
app . get ( '/health' , ( request : express . Request , response : express . Response ) => {
response . send ( 'OK' ) ;
} ) ;
// Do this:
app . get ( '/health' , ( request , response ) => {
// ^? (parameter) request: Request<...>
response . send ( 'OK' ) ;
// ^? (parameter) response: Response<...>
} ) ;
💻 playground
const elmo : Product = {
name : 'Tickle Me Elmo' ,
id : '048188 627152' ,
price : 28.99 ,
} ;
💻 playground
const furby = {
name : 'Furby' ,
id : 630509430963 ,
price : 35 ,
} ;
logProduct ( furby ) ;
// ~~~~~ Argument ... is not assignable to parameter of type 'Product'
// Types of property 'id' are incompatible
// Type 'number' is not assignable to type 'string'
💻 playground
const furby : Product = {
name : 'Furby' ,
id : 630509430963 ,
// ~~ Type 'number' is not assignable to type 'string'
price : 35 ,
} ;
logProduct ( furby ) ;
💻 playground
function getQuote ( ticker : string ) {
return fetch ( `https://quotes.example.com/?q=${ ticker } ` )
. then ( response => response . json ( ) ) ;
}
💻 playground
const cache : { [ ticker : string ] : number } = { } ;
function getQuote ( ticker : string ) {
if ( ticker in cache ) {
return cache [ ticker ] ;
}
return fetch ( `https://quotes.example.com/?q=${ ticker } ` )
. then ( response => response . json ( ) )
. then ( quote => {
cache [ ticker ] = quote ;
return quote as number ;
} ) ;
}
💻 playground
getQuote ;
// ^? function getQuote(ticker: string): number | Promise<number>
💻 playground
getQuote ( 'MSFT' ) . then ( considerBuying ) ;
// ~~~~ Property 'then' does not exist on type
// 'number | Promise<number>'
💻 playground
const cache : { [ ticker : string ] : number } = { } ;
function getQuote ( ticker : string ) : Promise < number > {
if ( ticker in cache ) {
return cache [ ticker ] ;
// ~~~ Type 'number' is not assignable to type 'Promise<number>'
}
// ...
}
💻 playground
interface Vector2D { x : number ; y : number ; }
function add ( a : Vector2D , b : Vector2D ) {
return { x : a . x + b . x , y : a . y + b . y } ;
}
💻 playground