TypeScript 2 in action

Preview:

Citation preview

TypeScript 2 in action

Александр Русаков / Techops

a_s_rusakov@mail.ru

github.com/arusakov

Немного истории

TypeScript 1.8 22 февраля 2016 г.

TypeScript 2.0 22 сентября 2016 г.

TypeScript 2.1 7 декабря 2016 г.

TypeScript 2.2 RC 2 февраля 2017 г.

blogs.msdn.microsoft.com/typescript/ 2

О чем пойдет речь ● Защита от Undefined / Null● Literal Types и что это такое● Размеченные объединения и Redux● Типизация для React Component API

3

Undefined everywhere

4

Undefined / Null

TypeError: Cannot read property 'x' of undefined

TypeError: Cannot read property 'y' of null

5

Undefined / Null type User = {

name: string

tags?: string[]

}

function getTags(user: User) {

return user.tags.join(', ')

}

6

type User = {

name: string

tags?: string[]

}

function getTags(user: User) {

return user.tags.join(', ')

}

Undefined / Null

7

type User = {

name: string

tags?: string[]

}

function getTags(user: User) {

return user.tags.join(', ')

}

Undefined / Null

8

Non-Nullable Types

https://github.com/Microsoft/TypeScript/pull/7140

// tsc --strictNullChecks

function getTags(user: User) {

return user.tags.join(', ')

}

// ERROR: Object is possibly 'undefined'

9

Non-Nullable Types// tsc --strictNullChecks

function getTagStrict(user: User) {

return user.tags && user.tags.join(', ')

}

10

Non-Null Assertion !// tsc --strictNullChecks

function getTagForce(user: User) {

return user.tags!.join(', ')

}

11

Literal Types

12

???

font-weight

13

Какие допустимые значения этого CSS свойства?

font-weight

14

Какие допустимые значения этого CSS свойства?

initial, inherit, unset,normal, bold, bolder, lighter100, 200, 300, 400, 500, 600, 700, 800, 900

https://www.w3.org/TR/css-fonts-3/#font-weight-prop

font-weight

15

type fontWeight = number | string

<div style={{ fontWeight: 1000 }} />

<div style={{ fontWeight: 'ligther' }} />

font-weight

16

type fontWeight = number | string

<div style={{ fontWeight: 1000 }} />

<div style={{ fontWeight: 'ligther' }} />

font-weight

17

type fontWeight = number | string

<div style={{ fontWeight: 1000 }} />

<div style={{ fontWeight: 'ligther' }} />

Literal Types

18

type fontWeight =

'initial' | 'inherit' | 'unset' |

'normal' | 'bold' | 'bolder' | 'lighter' |

100 | 200 | 300 | 400 | 500 |

600 | 700 | 800 | 900

https://github.com/Microsoft/TypeScript/pull/9407

Literal Types

19

<div style={{ fontWeight: 1000 }} />

<div style={{ fontWeight: 'ligther' }} />

// ERROR: Types of property 'fontWeight' are incompatible.

TypeScript 1 + Reduximport { Action } from 'redux' // Interface

const ACTION_TYPE_1 = 'type1'

interface Action1 extends Action {

data: number

}

20

TypeScript 1 + Reduxfunction reduce(state, action: Action) {

switch (action.type) {

case ACTION_TYPE_1:

action.data

}

}

21

TypeScript 1 + Reduxfunction reduce(state, action: Action) {

switch (action.type) {

case ACTION_TYPE_1:

action.data

}

}

// ERROR: Property 'data' does not exist on type 'Action'

22

TypeScript 1 + Redux

23

function reduce(state, action: Action) {

switch (action.type) {

case ACTION_TYPE_1:

(action as Action1).data // number

}

}

TypeScript 1 + Redux ≠ ♥

24

TypeScript 2

25

Discriminated Union Typestype Action =

{ type: 'type1', id: number } |

{ type: 'type2', name: string }

26https://github.com/Microsoft/TypeScript/pull/9163

Discriminated Union Typesconst ACTION_TYPE1 = 'type1'

const ACTION_TYPE2 = 'type2'

27

Discriminated Union Typesconst ACTION_TYPE1 = 'type1'

const ACTION_TYPE2 = 'type2'

type Action =

{ type: typeof ACTION_TYPE1, id: number } |

{ type: typeof ACTION_TYPE2, name: string }

28

TypeScript 2 ♥ Redux

https://spin.atomicobject.com/2016/09/27/typed-redux-reducers-typescript-2-0/

switch (action.type) {

case ACTION_TYPE1:

action.id // number

case ACTION_TYPE2:

action.name // string

}

29

React

30

TypeScript 1 + Reacttype State = { x: number, y: string }

this.state.x = 1

this.setState({ y: e.target.value })

31

TypeScript 1 + Reacttype State = { x: number, y: string }

this.state.x = 1

this.setState({ y: e.target.value })

// ERROR: Property 'x' is missing

32

TypeScript 1 + Reacttype State = { x: number, y: string }

this.state.x = 1

this.setState({ y: e.target.value } as State)

33

TypeScript 1 + React ≠ ♥

34

Index+Mapped Types// react.d.ts

class Component<P, S> {

setState<K extends keyof S>(s: Pick<S, K>): void;

props: Readonly<P>;

state: Readonly<S>;

}

35

https://github.com/Microsoft/TypeScript/pull/11929

https://github.com/Microsoft/TypeScript/pull/12114

TypeScript 2 ♥ React type State = { x: number, y: string }

this.state.x = 1

// ERROR: Cannot assign because it is a read-only property

this.setState({ y: e.target.value })

36

Predefined Mapped Types// lib.es6.d.ts

Pick<T, K extends keyof T>

Readonly<T>

Partial<T>

Record<K extends string, T>37

Спасибо за вниманиеВопросы?

Презентация и материалы: bit.ly/2kzGfOP

Александр Русаков / Techops

a_s_rusakov@mail.ru

github.com/arusakov