SlideShare ist ein Scribd-Unternehmen logo
1 von 48
Downloaden Sie, um offline zu lesen
React ! " TypeScript
Eine glückliche Ehe
Johann Böhler Karlsruhe, 25.6.2018
Alles so halb, nichts so richtig
2
Johann Böhler
Full-Stack Entwickler
3https://www.inovex.de/blog/komponentenbibliotheken/ , https://github.com/masinio/scrumlr.io
Case Studies
› Komponentenbasierte Library für Web UIs
› Framework im Baukastenprinzip
› JSX Syntax für Komponenten, angelehnt an HTML
› Mittlerweile MIT (seit September 2017)
4https://reactjs.org/
React
<div>
<h1 className="heading">Title</h1>
<Article>{content}</Article>
</div>
5
JSX
<div>
<h1 className="heading">Title</h1>
<Article>{content}</Article>
</div>
6
JSX
<div className="article">
{children}
</div>
7Refactoring: Improving the Design of Existing Code, 1999
Any fool can write code that a computer can
understand.
Good programmers write code that humans can
understand.
Martin Fowler
› Gesteigertes Verständnis? Vielleicht ...
› Definitiv aber Teil der Dokumentation
› Statische Typen können Fehler reduzieren
› ... müssen aber nicht, siehe Quelle
› IDE Unterstützung
› Assistenz
› Refactoring
8https://labs.ig.com/static-typing-promise
Statische Typisierung
9https://github.com/niieani/typescript-vs-flowtype
Vergleich
TypeScript vs. Flow
› Programmiersprache
› Starke Verbreitung
› Performance
› Meist einheitliche
Codebase, Migration aus
JS möglich
› Nur Validierung
› Mäßige Verbreitung, mehr
in React Native
› Langsam
› Optional, Migration aus JS
problemlos
› Typgenauer für React
10https://github.com/Microsoft/TypeScript-React-Starter
npm install -g create-react-app
create-react-app my-app --scripts-version=react-scripts-ts
Quickstart
› .jsx wird zu .tsx
› PropTypes ➡ ♻ ➡ #
11https://www.typescriptlang.org/docs/handbook/jsx.html
Zu beachten
Veränderungen gegenüber JavaScript
› <>-Casts werden zu as-Casts
› <MyClass> someObject
› someObject as MyClass
› https://github.com/Microsoft/TypeScript-React-Starter/issues/8
import * as ...
12https://www.typescriptlang.org/docs/handbook/jsx.html
Zu beachten
Veränderungen gegenüber TypeScript
13
// src/components/Hello.jsx
import React from 'react';
import PropTypes from 'prop-types';
const Hello = ({name, enthusiasmLevel = 1}) => {
if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {name + Array(enthusiasmLevel + 1).join('!')}
</div>
</div>
);
};
Hello.propTypes = {
name: PropTypes.string.isRequired,
enthusiasmLevel: PropTypes.number
};
14
// src/components/Hello.tsx
import * as React from 'react';
interface Props {
name: string;
enthusiasmLevel?: number;
}
const Hello: React.SFC<Props> = ({name, enthusiasmLevel = 1}) => {
if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {name + Array(enthusiasmLevel + 1).join('!')}
</div>
</div>
);
};
15
// src/components/Hello.tsx
import * as React from 'react';
interface Props {
name: string;
enthusiasmLevel?: number;
}
function Hello({name, enthusiasmLevel = 1}: Props) {
if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {name + Array(enthusiasmLevel + 1).join('!')}
</div>
</div>
);
}
16
// src/components/Hello.tsx
import * as React from 'react';
interface Props {
name: string;
enthusiasmLevel?: number;
}
class Hello extends React.Component<Props, {}> {
render() {
if (this.props.enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {this.props.name + Array(this.props.enthusiasmLevel + 1).join('!')}
</div>
</div>
);
}
}
Was ist mit ...
Default Props
17
18
// src/components/Greeting.tsx
import * as React from 'react';
export interface Props {
name?: string;
className?: string;
// some other props
[key: string]: any;
}
export class Greeting extends React.Component<Props, {}> {
static defaultProps: Partial<Props> = {
name: 'Stranger‘
};
render() {
return <span>Hello {this.props.name}</span>;
}
}
Was ist mit ...
State
19
20
// src/components/Greeting.tsx
import * as React from 'react';
export interface Props {
initialCount: number;
}
export interface State {
count: number;
}
export class Counter extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {count: props.initialCount};
}
increment = () => {
this.setState({count: this.state.count + 1});
};
render() {
return (
<>
<span>Count {this.state.count}</span>
<button onClick={this.increment}>Increment</button>
</>
);
}
}
Exkurs
Generics
21
22https://www.typescriptlang.org/docs/handbook/generics.html
// src/generics.ts
function identity(arg: any): any {
return arg;
}
const output: string = <string> identity("myString");;
23https://www.typescriptlang.org/docs/handbook/generics.html
// src/generics.ts
function identity(arg: any): any {
return arg;
}
function identity<T>(arg: T): T {
return arg;
}
const output: string = identity<string>('myString');
24https://www.typescriptlang.org/docs/handbook/generics.html
// src/generics.ts
function logArrayLenght<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}
function logActionType<T extends Action>(arg: T): T {
console.log(arg.type);
return arg;
}
25http://www.typescriptlang.org/docs/handbook/advanced-types.html
// src/union.ts
interface A {
name: string;
}
interface B {
age: number;
}
type Union = A & B;
const person: Union = {
name: 'Max Mustermann‘,
age: 12
};
Was ist mit ...
Higher Order Components
26
27https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb
// src/hoc/WithLoading.tsx
interface WithLoadingProps {
loading: boolean;
}
const withLoading = <P extends object>(Component: React.ComponentType<P>) =>
class WithLoading extends React.Component<P & WithLoadingProps> {
render() {
const {loading, ...props} = this.props as WithLoadingProps;
return loading ? <LoadingSpinner /> : <Component {...props} />;
}
};
28https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb
// src/hoc/WithLoading.tsx
interface WithLoadingProps {
loading: boolean;
}
const withLoading = <P extends object>(Component: React.ComponentType<P>): React.SFC<P & WithLoadingProps> =>
({loading, ...props}: WithLoadingProps) => (loading ? <LoadingSpinner /> : <Component {...props} />);
Was ist mit ...
Redux
29
30https://github.com/Microsoft/TypeScript-React-Starter
// src/types/index.tsx
export interface StoreState {
languageName: string;
enthusiasmLevel: number;
}
31https://github.com/Microsoft/TypeScript-React-Starter
// src/constants/index.tsx
export const INCREMENT_ENTHUSIASM = 'INCREMENT_ENTHUSIASM';
export type INCREMENT_ENTHUSIASM = typeof INCREMENT_ENTHUSIASM;
export const DECREMENT_ENTHUSIASM = 'DECREMENT_ENTHUSIASM';
export type DECREMENT_ENTHUSIASM = typeof DECREMENT_ENTHUSIASM;
32https://github.com/Microsoft/TypeScript-React-Starter
// src/actions/index.tsx
import * as constants from '../constants';
export interface IncrementEnthusiasm {
type: constants.INCREMENT_ENTHUSIASM;
}
export interface DecrementEnthusiasm {
type: constants.DECREMENT_ENTHUSIASM;
}
export type EnthusiasmAction = IncrementEnthusiasm | DecrementEnthusiasm;
export function incrementEnthusiasm(): IncrementEnthusiasm {
return {type: constants.INCREMENT_ENTHUSIASM};
}
export function decrementEnthusiasm(): DecrementEnthusiasm {
return {type: constants.DECREMENT_ENTHUSIASM};
}
33https://github.com/Microsoft/TypeScript-React-Starter
// src/reducers/index.tsx
import {EnthusiasmAction} from '../actions';
import {StoreState} from '../types/index';
import {DECREMENT_ENTHUSIASM, INCREMENT_ENTHUSIASM} from '../constants/index';
export function enthusiasm(state: StoreState, action: EnthusiasmAction): StoreState {
switch (action.type) {
case INCREMENT_ENTHUSIASM:
return {...state, enthusiasmLevel: state.enthusiasmLevel + 1};
case DECREMENT_ENTHUSIASM:
return {...state, enthusiasmLevel: Math.max(1, state.enthusiasmLevel - 1)};
}
return state;
}
34https://github.com/Microsoft/TypeScript-React-Starter
// src/components/Hello.container.tsx
import {connect, Dispatch} from 'react-redux';
import {StoreState} from '../types/index';
import * as actions from '../actions/';
import {Hello} from './Hello';
export function mapStateToProps({enthusiasmLevel, languageName}: StoreState) {
return {
enthusiasmLevel,
name: languageName
};
}
export function mapDispatchToProps(dispatch: Dispatch<actions.EnthusiasmAction>) {
return {
onIncrement: () => dispatch(actions.incrementEnthusiasm()),
onDecrement: () => dispatch(actions.decrementEnthusiasm())
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Hello);
Was ist mit ...
Redux und Props
35
› Initiale Props
› Props mit State
› Props mit Dispatch
› Props gemerged
36
Connect
Props in vier Bausteinen
37index.d.ts von @types/react-redux
export declare function connect<TStateProps, no_dispatch, TOwnProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>
): ComponentDecorator<TStateProps, TOwnProps>;
export declare function connect<no_state, TDispatchProps, TOwnProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
): ComponentDecorator<TDispatchProps, TOwnProps>;
export declare function connect<TStateProps, TDispatchProps, TOwnProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>;
export declare function connect<TStateProps, no_dispatch, TOwnProps, TMergedProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>,
mapDispatchToProps: null | undefined,
mergeProps: MergeProps<TStateProps, undefined, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
export declare function connect<no_state, TDispatchProps, TOwnProps, TMergedProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
mergeProps: MergeProps<undefined, TDispatchProps, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
export declare function connect<no_state, no_dispatch, TOwnProps, TMergedProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: null | undefined,
mergeProps: MergeProps<undefined, undefined, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
...
38
export interface OwnProps {
// ...
}
export interface StateProps {
// ...
}
export type Props = OwnProps & StateProps;
export const mapStateToProps = (state: any, ownProps: OwnProps): Props {
// ...
}
connect<StateFocusedCardProps, null, OwnFocusedCardProps>(mapStateToProps)(Component);
39index.d.ts von @types/react-redux
export declare function connect<TStateProps, no_dispatch, TOwnProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>
): ComponentDecorator<TStateProps, TOwnProps>;
export declare function connect<no_state, TDispatchProps, TOwnProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
): ComponentDecorator<TDispatchProps, TOwnProps>;
export declare function connect<TStateProps, TDispatchProps, TOwnProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>;
export declare function connect<TStateProps, no_dispatch, TOwnProps, TMergedProps>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>,
mapDispatchToProps: null | undefined,
mergeProps: MergeProps<TStateProps, undefined, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
export declare function connect<no_state, TDispatchProps, TOwnProps, TMergedProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
mergeProps: MergeProps<undefined, TDispatchProps, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
export declare function connect<no_state, no_dispatch, TOwnProps, TMergedProps>(
mapStateToProps: null | undefined,
mapDispatchToProps: null | undefined,
mergeProps: MergeProps<undefined, undefined, TOwnProps, TMergedProps>
): ComponentMergeDecorator<TMergedProps, TOwnProps>;
...
Was ist mit ...
Styled Components
40
41
// src/components/MyH1.tsx
import * as React from 'react';
import {default as styled} from 'styled-components';
const MyH1 = styled.h1`
color: red;
`;
42https://github.com/patrick91/Styled-Components-Typescript-Example/blob/master/src/theme/index.ts
// src/theme/index.ts
import * as styledComponents from 'styled-components';
const {
default: styled,
css,
injectGlobal,
keyframes,
ThemeProvider
} = styledComponents as styledComponents.ThemedStyledComponentsModule<IThemeInterface>;
export interface IThemeInterface {
primaryColor: string;
}
export const theme = {
primaryColor: '#e9e9eb'
};
export default styled;
export {css, injectGlobal, keyframes, ThemeProvider};
43https://github.com/patrick91/Styled-Components-Typescript-Example/blob/master/src/components/quote.tsx
// src/components/quote.tsx
import styled from '../theme';
const Quote = styled.h1`
color: ${props => props.theme.primaryColor};
font: 400 36px/1.4 'cardo';
font-style: italic;
font-weight: normal;
text-align: left;
text-indent: -10px;
max-width: 800px;
width: 80%;
margin: 0 auto;
`;
export default Quote;
Was ist mit ...
Enzyme
44
45
interface ShallowWrapper<P = {}, S = {}> extends CommonWrapper<P, S> {}
interface ReactWrapper<P = {}, S = {}> extends CommonWrapper<P, S> {}
...
const ShallowRendered: ShallowWrapper<Props, State> = shallow(<Hello />);
const MountRendered: ReactWrapper<Props, State> = mount(<Hello />);
Was ist mit ...
Code Style
46
TSLint
https://github.com/prettier/prettier, https://palantir.github.io/tslint/
› MobX
› React Router
› react-transition-group
› Firebase
› Jest, Mocha, Chai, Sinon
› Moment.js
› Fetch & Axios
› Styleguidist & Storybook
› ...
47
TypeScript Support
Vielen Dank
Johann Böhler
inovex GmbH
Ludwig-Erhard-Allee 6
76131 Karlsruhe
jboehler@inovex.de
0173 3181 182

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
KISS Automation.py
KISS Automation.pyKISS Automation.py
KISS Automation.py
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Information security programming in ruby
Information security programming in rubyInformation security programming in ruby
Information security programming in ruby
 
groovy & grails - lecture 13
groovy & grails - lecture 13groovy & grails - lecture 13
groovy & grails - lecture 13
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Php Debugger
Php DebuggerPhp Debugger
Php Debugger
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
httpie
httpiehttpie
httpie
 
Getting testy with Perl
Getting testy with PerlGetting testy with Perl
Getting testy with Perl
 
Django a whirlwind tour
Django   a whirlwind tourDjango   a whirlwind tour
Django a whirlwind tour
 
Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++Going native with less coupling: Dependency Injection in C++
Going native with less coupling: Dependency Injection in C++
 
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGroovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
 
Web develop in flask
Web develop in flaskWeb develop in flask
Web develop in flask
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
Web ui tests examples with selenide, nselene, selene & capybara
Web ui tests examples with  selenide, nselene, selene & capybaraWeb ui tests examples with  selenide, nselene, selene & capybara
Web ui tests examples with selenide, nselene, selene & capybara
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
 
InterConnect: Java, Node.js and Swift - Which, Why and When
InterConnect: Java, Node.js and Swift - Which, Why and WhenInterConnect: Java, Node.js and Swift - Which, Why and When
InterConnect: Java, Node.js and Swift - Which, Why and When
 

Ähnlich wie React mit TypeScript – eine glückliche Ehe

Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
Andy Peterson
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
intelliyole
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based Games
Ray Toal
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 

Ähnlich wie React mit TypeScript – eine glückliche Ehe (20)

Getting Started with React v16
Getting Started with React v16Getting Started with React v16
Getting Started with React v16
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.NativeConnect.js - Exploring React.Native
Connect.js - Exploring React.Native
 
React
React React
React
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
React outbox
React outboxReact outbox
React outbox
 
SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark BrocatoSenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
React - Start learning today
React - Start learning today React - Start learning today
React - Start learning today
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
React & The Art of Managing Complexity
React &  The Art of Managing ComplexityReact &  The Art of Managing Complexity
React & The Art of Managing Complexity
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based Games
 
ReactJS presentation
ReactJS presentationReactJS presentation
ReactJS presentation
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
 
React native app with type script tutorial
React native app with type script tutorialReact native app with type script tutorial
React native app with type script tutorial
 
Building Applications Using Ajax
Building Applications Using AjaxBuilding Applications Using Ajax
Building Applications Using Ajax
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 

Mehr von inovex GmbH

Interpretable Machine Learning
Interpretable Machine LearningInterpretable Machine Learning
Interpretable Machine Learning
inovex GmbH
 
Deep Learning for Recommender Systems
Deep Learning for Recommender SystemsDeep Learning for Recommender Systems
Deep Learning for Recommender Systems
inovex GmbH
 
Representation Learning von Zeitreihen
Representation Learning von ZeitreihenRepresentation Learning von Zeitreihen
Representation Learning von Zeitreihen
inovex GmbH
 
Performance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use casePerformance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use case
inovex GmbH
 

Mehr von inovex GmbH (20)

lldb – Debugger auf Abwegen
lldb – Debugger auf Abwegenlldb – Debugger auf Abwegen
lldb – Debugger auf Abwegen
 
Are you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AIAre you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AI
 
Why natural language is next step in the AI evolution
Why natural language is next step in the AI evolutionWhy natural language is next step in the AI evolution
Why natural language is next step in the AI evolution
 
WWDC 2019 Recap
WWDC 2019 RecapWWDC 2019 Recap
WWDC 2019 Recap
 
Network Policies
Network PoliciesNetwork Policies
Network Policies
 
Interpretable Machine Learning
Interpretable Machine LearningInterpretable Machine Learning
Interpretable Machine Learning
 
Jenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen UmgebungenJenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen Umgebungen
 
AI auf Edge-Geraeten
AI auf Edge-GeraetenAI auf Edge-Geraeten
AI auf Edge-Geraeten
 
Prometheus on Kubernetes
Prometheus on KubernetesPrometheus on Kubernetes
Prometheus on Kubernetes
 
Deep Learning for Recommender Systems
Deep Learning for Recommender SystemsDeep Learning for Recommender Systems
Deep Learning for Recommender Systems
 
Azure IoT Edge
Azure IoT EdgeAzure IoT Edge
Azure IoT Edge
 
Representation Learning von Zeitreihen
Representation Learning von ZeitreihenRepresentation Learning von Zeitreihen
Representation Learning von Zeitreihen
 
Talk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale AssistentenTalk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale Assistenten
 
Künstlich intelligent?
Künstlich intelligent?Künstlich intelligent?
Künstlich intelligent?
 
Dev + Ops = Go
Dev + Ops = GoDev + Ops = Go
Dev + Ops = Go
 
Das Android Open Source Project
Das Android Open Source ProjectDas Android Open Source Project
Das Android Open Source Project
 
Machine Learning Interpretability
Machine Learning InterpretabilityMachine Learning Interpretability
Machine Learning Interpretability
 
Performance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use casePerformance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use case
 
People & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madnessPeople & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madness
 
Infrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with PulumiInfrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with Pulumi
 

Kürzlich hochgeladen

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 

Kürzlich hochgeladen (20)

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 

React mit TypeScript – eine glückliche Ehe

  • 1. React ! " TypeScript Eine glückliche Ehe Johann Böhler Karlsruhe, 25.6.2018
  • 2. Alles so halb, nichts so richtig 2 Johann Böhler Full-Stack Entwickler
  • 4. › Komponentenbasierte Library für Web UIs › Framework im Baukastenprinzip › JSX Syntax für Komponenten, angelehnt an HTML › Mittlerweile MIT (seit September 2017) 4https://reactjs.org/ React
  • 7. 7Refactoring: Improving the Design of Existing Code, 1999 Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Martin Fowler
  • 8. › Gesteigertes Verständnis? Vielleicht ... › Definitiv aber Teil der Dokumentation › Statische Typen können Fehler reduzieren › ... müssen aber nicht, siehe Quelle › IDE Unterstützung › Assistenz › Refactoring 8https://labs.ig.com/static-typing-promise Statische Typisierung
  • 9. 9https://github.com/niieani/typescript-vs-flowtype Vergleich TypeScript vs. Flow › Programmiersprache › Starke Verbreitung › Performance › Meist einheitliche Codebase, Migration aus JS möglich › Nur Validierung › Mäßige Verbreitung, mehr in React Native › Langsam › Optional, Migration aus JS problemlos › Typgenauer für React
  • 10. 10https://github.com/Microsoft/TypeScript-React-Starter npm install -g create-react-app create-react-app my-app --scripts-version=react-scripts-ts Quickstart
  • 11. › .jsx wird zu .tsx › PropTypes ➡ ♻ ➡ # 11https://www.typescriptlang.org/docs/handbook/jsx.html Zu beachten Veränderungen gegenüber JavaScript
  • 12. › <>-Casts werden zu as-Casts › <MyClass> someObject › someObject as MyClass › https://github.com/Microsoft/TypeScript-React-Starter/issues/8 import * as ... 12https://www.typescriptlang.org/docs/handbook/jsx.html Zu beachten Veränderungen gegenüber TypeScript
  • 13. 13 // src/components/Hello.jsx import React from 'react'; import PropTypes from 'prop-types'; const Hello = ({name, enthusiasmLevel = 1}) => { if (enthusiasmLevel <= 0) { throw new Error('You could be a little more enthusiastic. :D'); } return ( <div className="hello"> <div className="greeting"> Hello {name + Array(enthusiasmLevel + 1).join('!')} </div> </div> ); }; Hello.propTypes = { name: PropTypes.string.isRequired, enthusiasmLevel: PropTypes.number };
  • 14. 14 // src/components/Hello.tsx import * as React from 'react'; interface Props { name: string; enthusiasmLevel?: number; } const Hello: React.SFC<Props> = ({name, enthusiasmLevel = 1}) => { if (enthusiasmLevel <= 0) { throw new Error('You could be a little more enthusiastic. :D'); } return ( <div className="hello"> <div className="greeting"> Hello {name + Array(enthusiasmLevel + 1).join('!')} </div> </div> ); };
  • 15. 15 // src/components/Hello.tsx import * as React from 'react'; interface Props { name: string; enthusiasmLevel?: number; } function Hello({name, enthusiasmLevel = 1}: Props) { if (enthusiasmLevel <= 0) { throw new Error('You could be a little more enthusiastic. :D'); } return ( <div className="hello"> <div className="greeting"> Hello {name + Array(enthusiasmLevel + 1).join('!')} </div> </div> ); }
  • 16. 16 // src/components/Hello.tsx import * as React from 'react'; interface Props { name: string; enthusiasmLevel?: number; } class Hello extends React.Component<Props, {}> { render() { if (this.props.enthusiasmLevel <= 0) { throw new Error('You could be a little more enthusiastic. :D'); } return ( <div className="hello"> <div className="greeting"> Hello {this.props.name + Array(this.props.enthusiasmLevel + 1).join('!')} </div> </div> ); } }
  • 17. Was ist mit ... Default Props 17
  • 18. 18 // src/components/Greeting.tsx import * as React from 'react'; export interface Props { name?: string; className?: string; // some other props [key: string]: any; } export class Greeting extends React.Component<Props, {}> { static defaultProps: Partial<Props> = { name: 'Stranger‘ }; render() { return <span>Hello {this.props.name}</span>; } }
  • 19. Was ist mit ... State 19
  • 20. 20 // src/components/Greeting.tsx import * as React from 'react'; export interface Props { initialCount: number; } export interface State { count: number; } export class Counter extends React.Component<Props, State> { constructor(props: Props) { super(props); this.state = {count: props.initialCount}; } increment = () => { this.setState({count: this.state.count + 1}); }; render() { return ( <> <span>Count {this.state.count}</span> <button onClick={this.increment}>Increment</button> </> ); } }
  • 22. 22https://www.typescriptlang.org/docs/handbook/generics.html // src/generics.ts function identity(arg: any): any { return arg; } const output: string = <string> identity("myString");;
  • 23. 23https://www.typescriptlang.org/docs/handbook/generics.html // src/generics.ts function identity(arg: any): any { return arg; } function identity<T>(arg: T): T { return arg; } const output: string = identity<string>('myString');
  • 24. 24https://www.typescriptlang.org/docs/handbook/generics.html // src/generics.ts function logArrayLenght<T>(arg: Array<T>): Array<T> { console.log(arg.length); return arg; } function logActionType<T extends Action>(arg: T): T { console.log(arg.type); return arg; }
  • 25. 25http://www.typescriptlang.org/docs/handbook/advanced-types.html // src/union.ts interface A { name: string; } interface B { age: number; } type Union = A & B; const person: Union = { name: 'Max Mustermann‘, age: 12 };
  • 26. Was ist mit ... Higher Order Components 26
  • 27. 27https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb // src/hoc/WithLoading.tsx interface WithLoadingProps { loading: boolean; } const withLoading = <P extends object>(Component: React.ComponentType<P>) => class WithLoading extends React.Component<P & WithLoadingProps> { render() { const {loading, ...props} = this.props as WithLoadingProps; return loading ? <LoadingSpinner /> : <Component {...props} />; } };
  • 28. 28https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb // src/hoc/WithLoading.tsx interface WithLoadingProps { loading: boolean; } const withLoading = <P extends object>(Component: React.ComponentType<P>): React.SFC<P & WithLoadingProps> => ({loading, ...props}: WithLoadingProps) => (loading ? <LoadingSpinner /> : <Component {...props} />);
  • 29. Was ist mit ... Redux 29
  • 30. 30https://github.com/Microsoft/TypeScript-React-Starter // src/types/index.tsx export interface StoreState { languageName: string; enthusiasmLevel: number; }
  • 31. 31https://github.com/Microsoft/TypeScript-React-Starter // src/constants/index.tsx export const INCREMENT_ENTHUSIASM = 'INCREMENT_ENTHUSIASM'; export type INCREMENT_ENTHUSIASM = typeof INCREMENT_ENTHUSIASM; export const DECREMENT_ENTHUSIASM = 'DECREMENT_ENTHUSIASM'; export type DECREMENT_ENTHUSIASM = typeof DECREMENT_ENTHUSIASM;
  • 32. 32https://github.com/Microsoft/TypeScript-React-Starter // src/actions/index.tsx import * as constants from '../constants'; export interface IncrementEnthusiasm { type: constants.INCREMENT_ENTHUSIASM; } export interface DecrementEnthusiasm { type: constants.DECREMENT_ENTHUSIASM; } export type EnthusiasmAction = IncrementEnthusiasm | DecrementEnthusiasm; export function incrementEnthusiasm(): IncrementEnthusiasm { return {type: constants.INCREMENT_ENTHUSIASM}; } export function decrementEnthusiasm(): DecrementEnthusiasm { return {type: constants.DECREMENT_ENTHUSIASM}; }
  • 33. 33https://github.com/Microsoft/TypeScript-React-Starter // src/reducers/index.tsx import {EnthusiasmAction} from '../actions'; import {StoreState} from '../types/index'; import {DECREMENT_ENTHUSIASM, INCREMENT_ENTHUSIASM} from '../constants/index'; export function enthusiasm(state: StoreState, action: EnthusiasmAction): StoreState { switch (action.type) { case INCREMENT_ENTHUSIASM: return {...state, enthusiasmLevel: state.enthusiasmLevel + 1}; case DECREMENT_ENTHUSIASM: return {...state, enthusiasmLevel: Math.max(1, state.enthusiasmLevel - 1)}; } return state; }
  • 34. 34https://github.com/Microsoft/TypeScript-React-Starter // src/components/Hello.container.tsx import {connect, Dispatch} from 'react-redux'; import {StoreState} from '../types/index'; import * as actions from '../actions/'; import {Hello} from './Hello'; export function mapStateToProps({enthusiasmLevel, languageName}: StoreState) { return { enthusiasmLevel, name: languageName }; } export function mapDispatchToProps(dispatch: Dispatch<actions.EnthusiasmAction>) { return { onIncrement: () => dispatch(actions.incrementEnthusiasm()), onDecrement: () => dispatch(actions.decrementEnthusiasm()) }; } export default connect(mapStateToProps, mapDispatchToProps)(Hello);
  • 35. Was ist mit ... Redux und Props 35
  • 36. › Initiale Props › Props mit State › Props mit Dispatch › Props gemerged 36 Connect Props in vier Bausteinen
  • 37. 37index.d.ts von @types/react-redux export declare function connect<TStateProps, no_dispatch, TOwnProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps> ): ComponentDecorator<TStateProps, TOwnProps>; export declare function connect<no_state, TDispatchProps, TOwnProps>( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps> ): ComponentDecorator<TDispatchProps, TOwnProps>; export declare function connect<TStateProps, TDispatchProps, TOwnProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps> ): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>; export declare function connect<TStateProps, no_dispatch, TOwnProps, TMergedProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>, mapDispatchToProps: null | undefined, mergeProps: MergeProps<TStateProps, undefined, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; export declare function connect<no_state, TDispatchProps, TOwnProps, TMergedProps>( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>, mergeProps: MergeProps<undefined, TDispatchProps, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; export declare function connect<no_state, no_dispatch, TOwnProps, TMergedProps>( mapStateToProps: null | undefined, mapDispatchToProps: null | undefined, mergeProps: MergeProps<undefined, undefined, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; ...
  • 38. 38 export interface OwnProps { // ... } export interface StateProps { // ... } export type Props = OwnProps & StateProps; export const mapStateToProps = (state: any, ownProps: OwnProps): Props { // ... } connect<StateFocusedCardProps, null, OwnFocusedCardProps>(mapStateToProps)(Component);
  • 39. 39index.d.ts von @types/react-redux export declare function connect<TStateProps, no_dispatch, TOwnProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps> ): ComponentDecorator<TStateProps, TOwnProps>; export declare function connect<no_state, TDispatchProps, TOwnProps>( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps> ): ComponentDecorator<TDispatchProps, TOwnProps>; export declare function connect<TStateProps, TDispatchProps, TOwnProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps> ): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>; export declare function connect<TStateProps, no_dispatch, TOwnProps, TMergedProps>( mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps>, mapDispatchToProps: null | undefined, mergeProps: MergeProps<TStateProps, undefined, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; export declare function connect<no_state, TDispatchProps, TOwnProps, TMergedProps>( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>, mergeProps: MergeProps<undefined, TDispatchProps, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; export declare function connect<no_state, no_dispatch, TOwnProps, TMergedProps>( mapStateToProps: null | undefined, mapDispatchToProps: null | undefined, mergeProps: MergeProps<undefined, undefined, TOwnProps, TMergedProps> ): ComponentMergeDecorator<TMergedProps, TOwnProps>; ...
  • 40. Was ist mit ... Styled Components 40
  • 41. 41 // src/components/MyH1.tsx import * as React from 'react'; import {default as styled} from 'styled-components'; const MyH1 = styled.h1` color: red; `;
  • 42. 42https://github.com/patrick91/Styled-Components-Typescript-Example/blob/master/src/theme/index.ts // src/theme/index.ts import * as styledComponents from 'styled-components'; const { default: styled, css, injectGlobal, keyframes, ThemeProvider } = styledComponents as styledComponents.ThemedStyledComponentsModule<IThemeInterface>; export interface IThemeInterface { primaryColor: string; } export const theme = { primaryColor: '#e9e9eb' }; export default styled; export {css, injectGlobal, keyframes, ThemeProvider};
  • 43. 43https://github.com/patrick91/Styled-Components-Typescript-Example/blob/master/src/components/quote.tsx // src/components/quote.tsx import styled from '../theme'; const Quote = styled.h1` color: ${props => props.theme.primaryColor}; font: 400 36px/1.4 'cardo'; font-style: italic; font-weight: normal; text-align: left; text-indent: -10px; max-width: 800px; width: 80%; margin: 0 auto; `; export default Quote;
  • 44. Was ist mit ... Enzyme 44
  • 45. 45 interface ShallowWrapper<P = {}, S = {}> extends CommonWrapper<P, S> {} interface ReactWrapper<P = {}, S = {}> extends CommonWrapper<P, S> {} ... const ShallowRendered: ShallowWrapper<Props, State> = shallow(<Hello />); const MountRendered: ReactWrapper<Props, State> = mount(<Hello />);
  • 46. Was ist mit ... Code Style 46 TSLint https://github.com/prettier/prettier, https://palantir.github.io/tslint/
  • 47. › MobX › React Router › react-transition-group › Firebase › Jest, Mocha, Chai, Sinon › Moment.js › Fetch & Axios › Styleguidist & Storybook › ... 47 TypeScript Support
  • 48. Vielen Dank Johann Böhler inovex GmbH Ludwig-Erhard-Allee 6 76131 Karlsruhe jboehler@inovex.de 0173 3181 182