Main resource: https://basarat.gitbook.io/typescript/
- Typescript is a superset of Javascript. The type system in Typescript is designed to be optional so that your Javascript is Typescript. It does not block Javascript emit in the presence of type errors, allowing users to progressively update JS to TS.
- Upgrading to TS without anyone noticing: https://devblogs.microsoft.com/typescript/how-to-upgrade-to-typescript-without-anybody-noticing-part-1/
- Migrating JS -> TS
- Add a
tsconfig.json
. - Convert files from
.js
to.ts
. Suppress errors usingany
. - Write new code in TS avoiding using
any
. - Go back to old code and start adding type annotations and fixing bugs.
- Use ambient definitions for third party JS code.
- Add a
- Make use of
readonly
andReadonly
,ReadonlyArray
etc features. -
I find it simplest to always be explicit about function returns. After all, these annotations are a theorem and the function body is the proof.
- You can use any prefix for generics, but it's common to use
T
, based on templates inC
. - Use ambient definitions in declaration files
*.d.ts
to suppress typescript errors in third party code. This can also be used for non-JS imports e.g.declare module "*.css"
lib.d.ts
includes declarations for most core JS interfaces and variables. You can edit this incompilerOptions
and supply additional libs (e.g.dom
,es6
).- DO NOT throw raw strings for errors. They become difficult to debug, always try to use the right errors. In fact, it's better to pass the
error
object itself around with callback (node
does this). - If a file has the extension
.d.ts
, then each root level definition must have thedeclare
keyword prefixed to it. Use aninterface
whenever possible instead of simply declaringany
. - Use
module: commonJs
intsconfig.json
- Study
Promise
. - Study
async/await
and understand how they use generators (function*
) under the hood. - Typescript has concept of "type declaration space" (
interface
,class
,type
) and "variable declaration space" (class
,var
,let
,const
etc). - Modules are looked up in order of
foo.js
,foo/index.js
,foo/package.json
(main
ortypes
field). - If we declare a module globally in
global.d.ts
, they will appear magically to that path. Prefer file-based modules for this though. - Recommended style guide: https://basarat.gitbook.io/typescript/styleguide
- Don't prefix interfaces with
I*
- Use
PascalCase
forEnum
,Class
,Interface
andcamelCase
for everything else. - Name files with
camelCase
. - Prefer
[]
instead ofArray<>
syntax for arrays.
- Don't prefix interfaces with
- If we need to emit JS, make sure the imported variables/types are actually used in code.
- Avoid circular dependencies.
- Avoid type assertions.
- Avoid
namespace
. Use external modules instead. enums
are numeric by nature. They are self-incrementing, so make use of number enums as flags (i.e. assignNone
enum key to the first entry so you can use it for falsy checks!): https://basarat.gitbook.io/typescript/type-system/enums#number-enums-as-flags- Use
interface
if you have types with hierarchies, allowing access toimplements
andextends
. Use type alias (i.e.type Foo = string | Bar
to provide semantic names, allowing easy setup with unions or intersections. - Explore dynamic import expressions in various projects.
npm install
andyarn add
only installs non-dev dependencies. If using@types/*
modules, install these asdevDependencies
.- Avoid
export default
: poor discoverability, error-prone refactors, cumbersome re-export syntax. - Turn on
noImplicitAny
andstrictNullChecks
. - Use the
!
non-null assertion + definite assignment assertion operators in applicable places. - Use
barrels
(i.e. re-exporting interfaces into a commonMyModule/index.js
). You can collect named exports into a variable and export that variable to expose the object of methods instead: https://basarat.gitbook.io/typescript/main-1/barrel - Authoring typescript libraries: https://basarat.gitbook.io/typescript/library
jest
has good typescript support: https://basarat.gitbook.io/typescript/intro-1/jest. Run it in--watch
mode.- Mapped types are useful. You can also use
keyof
andtypeof
vocabulary terms.type Index = 'a' | 'b' | 'c'; type FromIndex = { [k in Index]?: number } const colors = { red: 'reddish', blue: 'bluish', }; type Colors = keyof typeof colors; let color: Colors;
- React types in detail: https://basarat.gitbook.io/typescript/tsx/react
ReactNode
consolidatesJSX
andstring
.- You can specify the type to
React.ReactElement<T>
(e.g.React.ReactElement<MyAwesomeComponent>
inclass MyAwesomeComponent extends React.Component
) - Redux typescript in a nutshell: https://basarat.gitbook.io/typescript/type-system/discriminated-unions#redux
- At any time we do not have typescript types, we can declare these globally in the respective namespace for Typescript to pick up:
declare global {
namespace JSX {
interface IntrinsicElements {
'my-awesome-slider': MyAwesomeSliderProps;
}
interface MyAwesomeSliderProps extends React.Attributes {
name: string;
}
}
}
- Briefly how typescript works:
SourceCode ~~ scanner ~~> Token Stream ~~ parser ~~> AST ~~ binder ~~> Symbols
AST + Symbols ~~ checker ~~> Type Validation
AST + Checker ~~ emitter ~~> JS