From c5087e6911a1c4ab81d20cb95a478f93d4c3f52e Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Wed, 27 Jun 2018 12:57:25 +0200 Subject: [PATCH] style: apply prettier --- .../blogpost.md | 12 ++-- 2018-02/typesafe-redux/blogpost.md | 52 +++++++------- 2018-02/typesafe-redux/src/epic.ts | 8 +-- .../typesafe-redux/src/epics-with-enums.ts | 8 +-- .../src/epics-with-improved-of-type.ts | 4 +- 2018-02/typesafe-redux/src/of-type.ts | 2 +- .../blogpost.md | 32 ++++----- .../src/hoc-patterns/with-toggle.tsx | 2 +- .../src/render-cb-patterns/menu.tsx | 2 +- .../render-cb-patterns/with-toggleable.tsx | 2 +- .../blogpost.md | 70 +++++++++---------- .../ts-interface-vs-type-alias/blogpost.md | 18 ++--- 2018-05/ts-react-default-props/blogpost.md | 28 ++++---- .../app/default-props-solution-4-generics.tsx | 18 ++--- .../src/demo-meetup/app.tsx | 2 +- .../ts-react-new-features/src/provider.tsx | 2 +- 16 files changed, 131 insertions(+), 131 deletions(-) diff --git a/2018-02/private-properties-in-webcomponents/blogpost.md b/2018-02/private-properties-in-webcomponents/blogpost.md index 29b662e..9812980 100644 --- a/2018-02/private-properties-in-webcomponents/blogpost.md +++ b/2018-02/private-properties-in-webcomponents/blogpost.md @@ -6,9 +6,9 @@ In this article we will focus primarily on [**Unique Symbol Types**](https://git For our demonstration purpose, we will implement a simple `Toggleable Custom Element` with following featurs: -* it is both stateful and controllable component -* public API contains of 2 props: `title` and `show` and content projection via `slot` -* onClick it will toggle visibility of projected content +- it is both stateful and controllable component +- public API contains of 2 props: `title` and `show` and content projection via `slot` +- onClick it will toggle visibility of projected content **Usage:** @@ -26,9 +26,9 @@ Ok let's implement our `Toggleable` Custom Element: As we know, standard pattern to impement Custom Element props is following -* internal "private" class property which keeps current property value -* getter to that "private" property for public use -* setter for "private" property for public use +- internal "private" class property which keeps current property value +- getter to that "private" property for public use +- setter for "private" property for public use So let's say for our `title` prop following needs to be implemented diff --git a/2018-02/typesafe-redux/blogpost.md b/2018-02/typesafe-redux/blogpost.md index 45d731e..88cb760 100644 --- a/2018-02/typesafe-redux/blogpost.md +++ b/2018-02/typesafe-redux/blogpost.md @@ -14,9 +14,9 @@ At that time ( pre TS 2.8 era ) there wasn't a clean solution how to get the ret You had to do it like this: -* define type definition first, -* then implement action creator with return type annotated with your defined type -* when you changed one thing, you needed to manually update other and vice-versa, bleh... +- define type definition first, +- then implement action creator with return type annotated with your defined type +- when you changed one thing, you needed to manually update other and vice-versa, bleh... ```ts // you need to define the shape first @@ -44,11 +44,11 @@ Thanks to this addition, we can create new powerfull mapped types, let's say, fo Wait a second! It turns out we don't have to create anything at all, 'cause they are already a part of TS 2.8! We've got following new mapped types at our disposal: -* `Exclude` -- Exclude from T those types that are assignable to U. -* `Extract` -- Extract from T those types that are assignable to U. -* `NonNullable` -- Exclude null and undefined from T. -* `ReturnType` -- Obtain the return type of a function type. -* `InstanceType` -- Obtain the instance type of a constructor function type. +- `Exclude` -- Exclude from T those types that are assignable to U. +- `Extract` -- Extract from T those types that are assignable to U. +- `NonNullable` -- Exclude null and undefined from T. +- `ReturnType` -- Obtain the return type of a function type. +- `InstanceType` -- Obtain the instance type of a constructor function type. > for more info (check out this PR)[https://github.com/Microsoft/TypeScript/pull/21847] @@ -124,11 +124,11 @@ Now our inferred type is correct **PROS:** -* action type is inferred from implementation and because of that stays in sync! +- action type is inferred from implementation and because of that stays in sync! **CONS:** -* explicitly casting `type` property within action creator +- explicitly casting `type` property within action creator ## Reducing the action boilerplate (createAction) @@ -177,13 +177,13 @@ type SetAgeAction = ReturnType **PROS:** -* ( as before ) action type is inferred from implementation and because of that, it stays in sync! -* we don't have to cast our type -* more concise than before +- ( as before ) action type is inferred from implementation and because of that, it stays in sync! +- we don't have to cast our type +- more concise than before **CONS:** -* none I guess ? :) +- none I guess ? :) ## Reducing the action boilerplate further (action) @@ -248,13 +248,13 @@ With that our `DoSomethingAction` will have following type: **PROS:** -* ( as before ) action type is inferred from implementation and because of that, it stays in sync! -* ( as before ) we don't have to cast our type -* even more concise than `createAction` +- ( as before ) action type is inferred from implementation and because of that, it stays in sync! +- ( as before ) we don't have to cast our type +- even more concise than `createAction` **CONS:** -* if we wanna provide payload, we have to explicitly declare `typeof SET_AGE` as 1st generic argument, because TS isn't able to do that for us properly ( it will flatten string literal to just simple `string`) +- if we wanna provide payload, we have to explicitly declare `typeof SET_AGE` as 1st generic argument, because TS isn't able to do that for us properly ( it will flatten string literal to just simple `string`) ## Reducing the action boilerplate by using classes @@ -278,7 +278,7 @@ Everything is defined once -> implementaion and action type definition. Elegant > This can be mitigated via custom middleware, which shalow copies created instance to pure Object > > ```ts -> export const actionToPlainObject: MiddlewareFn<{}, Action> = store => next => action => +> export const actionToPlainObject: MiddlewareFn<{}, Action> = (store) => (next) => (action) => > next({ ...action }) > ``` > @@ -286,14 +286,14 @@ Everything is defined once -> implementaion and action type definition. Elegant **PROS:** -* implementation is also type definition because structural origin of TypeScript Classes -* concise and elegant +- implementation is also type definition because structural origin of TypeScript Classes +- concise and elegant **CONS:** -* constructor parameter named genericaly `payload`, which may not be very descriptive if payload is a primitive type -* (if you're using redux ) you need to provide custom middleware for flattening custom class instance to pure object -* using `new SetAgeAction(18)` may feel strange or just wrong to some functional purists, I don't mind personaly 😎, it makes it even more visible within component code that I'm creating a FSA +- constructor parameter named genericaly `payload`, which may not be very descriptive if payload is a primitive type +- (if you're using redux ) you need to provide custom middleware for flattening custom class instance to pure object +- using `new SetAgeAction(18)` may feel strange or just wrong to some functional purists, I don't mind personaly 😎, it makes it even more visible within component code that I'm creating a FSA ## And the winner is @@ -381,8 +381,8 @@ With that said, let’s grab some beer and popcorn and enjoy your 100% type-safe TypeScript 2.8 comes with very important new features: -* conditional types -* new default conditional mapped types, from which we can leverage `ReturnType` to get return types of a function +- conditional types +- new default conditional mapped types, from which we can leverage `ReturnType` to get return types of a function Thanks to these new features, TypeScript is able to infer action type of our action creator implementation, so we don't have to duplicate our work and keep type definition and implementaion in sync. diff --git a/2018-02/typesafe-redux/src/epic.ts b/2018-02/typesafe-redux/src/epic.ts index 542c17b..04dcfca 100644 --- a/2018-02/typesafe-redux/src/epic.ts +++ b/2018-02/typesafe-redux/src/epic.ts @@ -8,19 +8,19 @@ import { ActionsOfType } from './types' type SetAgeAction = ActionsOfType -const epic: Epic = actions$ => { +const epic: Epic = (actions$) => { return actions$.pipe( ofType(SET_AGE), - map(action => { + map((action) => { const { type, payload: newAge } = action return Actions.reloadUrl() }) ) } -const epicWithChainOfType: Epic = actions$ => { +const epicWithChainOfType: Epic = (actions$) => { return actions$.ofType(SET_AGE).pipe( - map(action => { + map((action) => { const { type, payload: newAge } = action return Actions.reloadUrl() }) diff --git a/2018-02/typesafe-redux/src/epics-with-enums.ts b/2018-02/typesafe-redux/src/epics-with-enums.ts index 8ccfdc3..0d4e319 100644 --- a/2018-02/typesafe-redux/src/epics-with-enums.ts +++ b/2018-02/typesafe-redux/src/epics-with-enums.ts @@ -8,19 +8,19 @@ import { ActionsOfType } from './types' type SetAgeAction = ActionsOfType -const epic: Epic = actions$ => { +const epic: Epic = (actions$) => { return actions$.pipe( ofType(ActionTypes.SET_AGE), - map(action => { + map((action) => { const { type, payload: newAge } = action return Actions.reloadUrl() }) ) } -const epicWithChainOfType: Epic = actions$ => { +const epicWithChainOfType: Epic = (actions$) => { return actions$.ofType(ActionTypes.SET_AGE).pipe( - map(action => { + map((action) => { const { type, payload: newAge } = action return Actions.reloadUrl() }) diff --git a/2018-02/typesafe-redux/src/epics-with-improved-of-type.ts b/2018-02/typesafe-redux/src/epics-with-improved-of-type.ts index 2d353b6..5a79ccf 100644 --- a/2018-02/typesafe-redux/src/epics-with-improved-of-type.ts +++ b/2018-02/typesafe-redux/src/epics-with-improved-of-type.ts @@ -9,11 +9,11 @@ import { SET_AGE, Actions } from './actions' import { State } from './store' // BEHOLD 100% type safe epic ! I ❤️ love it ! -const epic: Epic = actions$ => { +const epic: Epic = (actions$) => { return actions$.pipe( // ofType(ActionTypes.SET_AGE), ofType(SET_AGE), - map(action => { + map((action) => { const { type, payload: newAge } = action return Actions.reloadUrl() }) diff --git a/2018-02/typesafe-redux/src/of-type.ts b/2018-02/typesafe-redux/src/of-type.ts index f4d0417..77cdcbe 100644 --- a/2018-02/typesafe-redux/src/of-type.ts +++ b/2018-02/typesafe-redux/src/of-type.ts @@ -23,6 +23,6 @@ export function ofType< >(t1: T1, t2: T2, t3: T3): OperatorFunction> export function ofType(...types: string[]) { return function(source: Observable) { - return source.pipe(filter(action => types.indexOf(action.type) !== -1)) as any + return source.pipe(filter((action) => types.indexOf(action.type) !== -1)) as any } } diff --git a/2018-02/ultimate-react-component-patterns/blogpost.md b/2018-02/ultimate-react-component-patterns/blogpost.md index 98bf4cb..4abe235 100644 --- a/2018-02/ultimate-react-component-patterns/blogpost.md +++ b/2018-02/ultimate-react-component-patterns/blogpost.md @@ -206,9 +206,9 @@ that it is defined by `Component.defaultProps` React construct. To satisfy TS compiler we can use 3 techniques: -* use **Bang** operator to explicitly tell compiler that this won't be `undefined` within our render, although it is optional, like this: `` -* use **conditional statements/ternary operator** to make compiler understand that some particular prop is not undefined: `` -* create reusable `withDefaultProps` High order function, which will update our props type definition and will set our default props. This is the most clean solution, IMHO +- use **Bang** operator to explicitly tell compiler that this won't be `undefined` within our render, although it is optional, like this: `` +- use **conditional statements/ternary operator** to make compiler understand that some particular prop is not undefined: `` +- create reusable `withDefaultProps` High order function, which will update our props type definition and will set our default props. This is the most clean solution, IMHO ```ts export const withDefaultProps =

= Partial

>( @@ -371,7 +371,7 @@ const initialState = { show: false } type State = Readonly ``` -* here we are declaring our state as in previous examples, nothing new +- here we are declaring our state as in previous examples, nothing new Now we need to define our component props ( note that we are using Partial mapped type, as we know that all props are gonna be optional, instead of annotating every prop manually by `?` operator ): @@ -395,8 +395,8 @@ type ToggleableComponentProps = { show: State['show']; toggle: Toggleable['toggl Again we are using the power of typeScript and **lookup types**, so we don't have to repeat ourselves when defining types: -* `show: State['show']` we are creating our `show` prop type by leveraging existing type definition within our state -* `toggle: Toggleable['toggle']` we are leveraging type inference and structural nature of classes within TS by getting the type from our method implementation! nice and indeed powerful! +- `show: State['show']` we are creating our `show` prop type by leveraging existing type definition within our state +- `toggle: Toggleable['toggle']` we are leveraging type inference and structural nature of classes within TS by getting the type from our method implementation! nice and indeed powerful! The rest of the implementation is straightforward, standard _render props/children as function_ pattern: @@ -549,9 +549,9 @@ Now with that done, let's define our new API - `component` prop. We need update our props API. -* `children` can be now function or ReactNode ( when component prop is used) -* `component` is our new API which accepts component that needs to implement `ToggleableComponentProps` on it's props and it needs to be generic and set to `any`, so if arbitrary component that implements other properties than `ToggleableComponentProps` will pass TS validaion -* `props` we are introducing props property for passing down arbitrary props, this is a common pattern. It is defined as index type with any type, so we are loosing here strict type safety... +- `children` can be now function or ReactNode ( when component prop is used) +- `component` is our new API which accepts component that needs to implement `ToggleableComponentProps` on it's props and it needs to be generic and set to `any`, so if arbitrary component that implements other properties than `ToggleableComponentProps` will pass TS validaion +- `props` we are introducing props property for passing down arbitrary props, this is a common pattern. It is defined as index type with any type, so we are loosing here strict type safety... ```tsx // We need create defaultProps with our arbitrary prop type -> props which is gonna be empty object by default @@ -723,9 +723,9 @@ Let's implement our HOC: We need to create: -* displayName ( so we get nice debugging within devtools) -* WrappedComponent ( so we can access original component - useful for testing ) -* leverage `hoistNonReactStatics` from `hoist-non-react-statics` npm package +- displayName ( so we get nice debugging within devtools) +- WrappedComponent ( so we can access original component - useful for testing ) +- leverage `hoistNonReactStatics` from `hoist-non-react-statics` npm package ```tsx import React, { ComponentType, Component } from 'react' @@ -756,7 +756,7 @@ export const withToogleable = ( const { ...rest } = this.props return ( - } /> + } /> ) } } @@ -933,7 +933,7 @@ export const withToogleable = ( return ( } + render={(renderProps) => } /> ) } @@ -957,7 +957,7 @@ All demos can be found at [my Github repo](https://github.com/Hotell/blogposts/t Also it is very important to realise, that type safety within templates like demonstrated in this article, is possible only within libraries that use VDOM/JSX -* Angular templates with Language service provide type safety, but soundness fails on simple constructs like checking within ngFor etc... -* Vue has nothing like Angular implemented yet for templates, so their templates and data binding are just magical strings ( but this may change in the future. Although you can use VDOM for templates it's cumbersome to use because various types of props definition ( "snabdom takes the blame..." ) ) +- Angular templates with Language service provide type safety, but soundness fails on simple constructs like checking within ngFor etc... +- Vue has nothing like Angular implemented yet for templates, so their templates and data binding are just magical strings ( but this may change in the future. Although you can use VDOM for templates it's cumbersome to use because various types of props definition ( "snabdom takes the blame..." ) ) As always, don't hesitate to ping me if you have any questions here or on twitter (my handle [@martin_hotell](https://twitter.com/martin_hotell)) and besides that, happy type checking folks and 'till next time! Cheers! diff --git a/2018-02/ultimate-react-component-patterns/src/hoc-patterns/with-toggle.tsx b/2018-02/ultimate-react-component-patterns/src/hoc-patterns/with-toggle.tsx index 155c129..2b2fd43 100644 --- a/2018-02/ultimate-react-component-patterns/src/hoc-patterns/with-toggle.tsx +++ b/2018-02/ultimate-react-component-patterns/src/hoc-patterns/with-toggle.tsx @@ -35,7 +35,7 @@ export function withToggle( ) } private toggle = (event: MouseEvent) => - this.setState(prevState => ({ show: !prevState.show })) + this.setState((prevState) => ({ show: !prevState.show })) } return hoistNonReactStatics(WithToggle, UnwrappedComponent as any) as ComponentType diff --git a/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/menu.tsx b/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/menu.tsx index d4d54a6..69ca0c6 100644 --- a/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/menu.tsx +++ b/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/menu.tsx @@ -31,5 +31,5 @@ export class Menu extends Component<{}, State> { } private toggleShowContents = () => - this.setState(prevState => ({ showContents: !prevState.showContents })) + this.setState((prevState) => ({ showContents: !prevState.showContents })) } diff --git a/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/with-toggleable.tsx b/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/with-toggleable.tsx index 5df61c8..5c16506 100644 --- a/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/with-toggleable.tsx +++ b/2018-02/ultimate-react-component-patterns/src/render-cb-patterns/with-toggleable.tsx @@ -32,7 +32,7 @@ export const withToogleable = ( return ( } + render={(renderProps) => } /> ) } diff --git a/2018-03/react-tools-for-better-angular/blogpost.md b/2018-03/react-tools-for-better-angular/blogpost.md index f564d24..fdce787 100644 --- a/2018-03/react-tools-for-better-angular/blogpost.md +++ b/2018-03/react-tools-for-better-angular/blogpost.md @@ -24,9 +24,9 @@ By looking outside Angular "ecosystem isolation", we can learn a lot from others To answer the question "How to leverage other ecosystems" we need to to introduce and take a look at 3 categories that are an integral part of software development: -* Tools -* Architecture -* Libraries +- Tools +- Architecture +- Libraries As a baseline we will use "Industry standard" for booting up new Angular apps - **Angular CLI** ![Angular CLI](https://user-images.githubusercontent.com/1560278/27637944-cfa5df36-5c11-11e7-8cb7-85be0017faf1.gif) @@ -41,16 +41,16 @@ npx @angular/cli new my-app Let’s take a look what CLI gives us by default from perspective of our 3 defined categories: -* Libraries - all @angular/\* packages and RxJs +- Libraries - all @angular/\* packages and RxJs -* Architecture - Component driven architecture with Service layer, but no restrictions on this front ( use what you want ) +- Architecture - Component driven architecture with Service layer, but no restrictions on this front ( use what you want ) -* Tools: +- Tools: - * we’ve got webpack as a module bundler - * Protractor/Selenium for e2e testing - * Jasmine with Karma for unit testing - * and last but not least, the best thing that ever happened to JavaScript - Typescript with solid static analysis extensions for adhering to proper styleguides and - TSLint and Codelyzer + - we’ve got webpack as a module bundler + - Protractor/Selenium for e2e testing + - Jasmine with Karma for unit testing + - and last but not least, the best thing that ever happened to JavaScript - Typescript with solid static analysis extensions for adhering to proper styleguides and - TSLint and Codelyzer So far so good right ?! @@ -150,8 +150,8 @@ Formatting/Linting Done! Although there is a room for improvement. I don't know We can handle robots to do that for us. This can be achieved thanks to git-hooks and 2 node libraries: -* [lint-staged](https://github.com/okonet/lint-staged) 🚫💩 — Run linters/formatters on git staged files -* [husky](https://github.com/typicode/husky) 🐶 Git hooks made easy +- [lint-staged](https://github.com/okonet/lint-staged) 🚫💩 — Run linters/formatters on git staged files +- [husky](https://github.com/typicode/husky) 🐶 Git hooks made easy Install those: @@ -269,16 +269,16 @@ Beautiful isn’t it ?! There are moar things that comes with Jest, I will name just few: -* Powerful mocking features ( ES2015 modules, assets ) -* Code coverage - 0CJS `jest --coverage` -* Pluggable ( run Puppeteer with Jest ) -* Huge ecosystem: [jest-axe](https://github.com/nickcolley/jest-axe) ( a11y ), [jest-images-snapshots](https://github.com/americanexpress/jest-image-snapshot) +- Powerful mocking features ( ES2015 modules, assets ) +- Code coverage - 0CJS `jest --coverage` +- Pluggable ( run Puppeteer with Jest ) +- Huge ecosystem: [jest-axe](https://github.com/nickcolley/jest-axe) ( a11y ), [jest-images-snapshots](https://github.com/americanexpress/jest-image-snapshot) ### E2E Testing End to End testing is equally or even more important than unit testing. Let's see what we get by default with CLI. -* Protractor with Selenium +- Protractor with Selenium Uh?! what did you just said? Selenium ? I dunno about you but everytime I hear “SELENIUM” I wanna fight someone... @@ -394,10 +394,10 @@ With storybook covered, our final component folder structure should look like th ![Storybook - Component folder structure](./img/storybook-final-component-folder-structure.png) -* implementation -* unit test with snapshots -* external styles -* story +- implementation +- unit test with snapshots +- external styles +- story ### Tooling summary @@ -415,8 +415,8 @@ We can use similar patterns that are effectively used within other libraries ( i Those common patterns can be applied in 2 most important parts of every app: -* Components -* State management +- Components +- State management ### Architecture: Components @@ -424,11 +424,11 @@ Following image compares both Angular and React in terms of Component creation p ![Component patterns comparison](./img/component-patterns.png) -* React.Component/@Component -* HOC/@Directive ( HOC just decorates behaviour in immutable way, Directive can do the same in Angular ) -* render JSX/Inline template ( Always use Inline templates to have everything in one file, logic + rendering ) -* Inline/External CSS -* Immutable props/@Input with CDS.OnPush ( React triggers re-render only when reference changes, Angular allows the same via OnPush strategy ) +- React.Component/@Component +- HOC/@Directive ( HOC just decorates behaviour in immutable way, Directive can do the same in Angular ) +- render JSX/Inline template ( Always use Inline templates to have everything in one file, logic + rendering ) +- Inline/External CSS +- Immutable props/@Input with CDS.OnPush ( React triggers re-render only when reference changes, Angular allows the same via OnPush strategy ) Also very important pattern to for building components [Stateful<->Stateless component pattern](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). @@ -440,9 +440,9 @@ It can be handled similarly in both React and Angular: ![State management types](./img/state-management-types.png) -* Local Component state ( this.state ) / @Component|@Directive instance state => suitable for private state ( mostly UI state) -* Hierarchical Context API supported by SOA / Hierarchical DI in Angular => suitable for whole app state -* FLUX architecture powered by Redux => **most suitable for app state, and universal for both Angular and React** +- Local Component state ( this.state ) / @Component|@Directive instance state => suitable for private state ( mostly UI state) +- Hierarchical Context API supported by SOA / Hierarchical DI in Angular => suitable for whole app state +- FLUX architecture powered by Redux => **most suitable for app state, and universal for both Angular and React** So as we can see, **Redux is the ultimate solution for both React and Angular** in terms of true State separation. Thanks to this separation we can write Redux boilerplate once and literally reuse it in both Angular or React. With FLUX architecture, only feature that we're leveraging in any UI framework is hydratation of data to our view ( components ) and rendering. @@ -486,8 +486,8 @@ yarn add redux-observable rxjs It's similar to Effects with 2 important distinctions: -* Epics are executed after all reducers -* Epic needs to always return an Action Stream ( Actions in, Actions out - thanks to that, it prevents us to introduce anti-patterns, that can be observed within ngrx/effects, for instance using `tap` and similar noop operators, for triggering side effects within effects ) +- Epics are executed after all reducers +- Epic needs to always return an Action Stream ( Actions in, Actions out - thanks to that, it prevents us to introduce anti-patterns, that can be observed within ngrx/effects, for instance using `tap` and similar noop operators, for triggering side effects within effects ) > **NOTE:** If you have absolutely no other option and need to execute side effect like within Effects, you can do that and comlplete the current stream so nothing get's emitted futher via [`ignoreElements` Rx operator](https://www.learnrxjs.io/operators/filtering/ignoreelements.html). @@ -551,8 +551,8 @@ Our final Angular CLI solution looks like this: You can find everything that I've covered in this article open sourced on my GitHub repo: -* [Better Angular CLI defaults](https://github.com/Hotell/react-tools-for-better-angular-apps) -* [Example app](https://github.com/Hotell/react-tools-for-better-angular-apps/tree/example-app) +- [Better Angular CLI defaults](https://github.com/Hotell/react-tools-for-better-angular-apps) +- [Example app](https://github.com/Hotell/react-tools-for-better-angular-apps/tree/example-app) --- diff --git a/2018-03/ts-interface-vs-type-alias/blogpost.md b/2018-03/ts-interface-vs-type-alias/blogpost.md index b9e03d3..e2dcf28 100644 --- a/2018-03/ts-interface-vs-type-alias/blogpost.md +++ b/2018-03/ts-interface-vs-type-alias/blogpost.md @@ -254,7 +254,7 @@ There is a very suble difference though. You will get the particular shape type What is usually a good idea/practice, is to disect our hybrid definition in two parts: -* callable object (function) type alias +- callable object (function) type alias ```ts // via type alias @@ -268,7 +268,7 @@ interface CounterFn { ![Hybrid Types Functions](./img/hybrid-types-1.png) -* static properties object shape +- static properties object shape ```ts // via type alias @@ -422,9 +422,9 @@ This is the only use case, where you definitely should always use interface inst In general, use what you want ( type aliase / interface ) just be consistent, but personally, I recomend to use type aliases: -* it's shorter to write `type Props = {}` -* your syntax is consistent ( you are not mixin interfaces with type aliase for possible type intersections ) -* your component Props/State implementation cannot be monkey patched and for that reason, consumer of your component should never need to leverage interface declaration merging. For extension there are clearly defined patterns like HOC and so on. +- it's shorter to write `type Props = {}` +- your syntax is consistent ( you are not mixin interfaces with type aliase for possible type intersections ) +- your component Props/State implementation cannot be monkey patched and for that reason, consumer of your component should never need to leverage interface declaration merging. For extension there are clearly defined patterns like HOC and so on. ## Summary @@ -434,10 +434,10 @@ With that covered, we came to an conclusion what method of defining compile time Let's recap: -* type aliases can act sort of like interfaces, however, there are 3 important differences ( union types, declaration merging) -* use whatever suites you and your team, just be consistent -* always use `interface` for public API's definition when authoring a library or 3rd party ambient type definitions -* consider using `type` for your React Component Props and State +- type aliases can act sort of like interfaces, however, there are 3 important differences ( union types, declaration merging) +- use whatever suites you and your team, just be consistent +- always use `interface` for public API's definition when authoring a library or 3rd party ambient type definitions +- consider using `type` for your React Component Props and State --- diff --git a/2018-05/ts-react-default-props/blogpost.md b/2018-05/ts-react-default-props/blogpost.md index 4556a24..ce956b4 100644 --- a/2018-05/ts-react-default-props/blogpost.md +++ b/2018-05/ts-react-default-props/blogpost.md @@ -12,9 +12,9 @@ So let's define a `Button` component, with following API, which will be used acr **Button API** -* onClick ( click handler ) -* color ( what color will be used ) -* type (button type 'button' or 'submit') +- onClick ( click handler ) +- color ( what color will be used ) +- type (button type 'button' or 'submit') We will annotate `color` and `type` as optional, because they will be defined via defaultProps, so consumer of our component doesn't have to provide those. @@ -72,8 +72,8 @@ Our `Button`s `defaultProps` are not typed at all, because type checker cannot i What does that even mean? -* you can set anything to your `static defaultProps` -* your are defining same things twice ( types and implementation ) +- you can set anything to your `static defaultProps` +- your are defining same things twice ( types and implementation ) No type checking for defaultProps: @@ -185,10 +185,10 @@ Why do we get an error now? Well `color` is optional, and we are in strict mode, As of today _June 2018/TypeScript 2.9_ there are 4 options how to fix this: -* Non-null assertion operator -* Component type casting -* High order function for defining defaultProps -* Props getter function +- Non-null assertion operator +- Component type casting +- High order function for defining defaultProps +- Props getter function Let's take a look at those one by one. @@ -411,11 +411,11 @@ This is very slick, don't you think ? We are done here, this final solution covers all former issues: -* no need for escape hatches by using non null assertion operator -* no need to cast our component to other types with more indirection ( additional const Button ) -* we don't have to re-create component implementation and thus loosing any types in the process ( withDefaultProps function ) -* works with generic components -* easy to reason about and future proof ( TypeScript 3.0 ) +- no need for escape hatches by using non null assertion operator +- no need to cast our component to other types with more indirection ( additional const Button ) +- we don't have to re-create component implementation and thus loosing any types in the process ( withDefaultProps function ) +- works with generic components +- easy to reason about and future proof ( TypeScript 3.0 ) ## TypeScript 3.0 diff --git a/2018-05/ts-react-default-props/src/app/default-props-solution-4-generics.tsx b/2018-05/ts-react-default-props/src/app/default-props-solution-4-generics.tsx index d8d2213..d1ad93a 100644 --- a/2018-05/ts-react-default-props/src/app/default-props-solution-4-generics.tsx +++ b/2018-05/ts-react-default-props/src/app/default-props-solution-4-generics.tsx @@ -29,16 +29,16 @@ class Button extends Component> { } } -const ButtonSFC = (props:Props) => { +const ButtonSFC = (props: Props) => { const { onClick: handleClick, color, type, children } = getProps(props) - const cssClass = resolveColorTheme(color) + const cssClass = resolveColorTheme(color) - return ( - - ) + return ( + + ) } const resolveColorTheme = (color: DefaultProps['color']) => { @@ -58,8 +58,8 @@ class App extends Component { render() { return (

- - onClick={this.handleClick}>Click me! + onClick={this.handleClick}>Click me! + onClick={this.handleClick}>Click me!
) } diff --git a/2018-05/ts-react-new-features/src/demo-meetup/app.tsx b/2018-05/ts-react-new-features/src/demo-meetup/app.tsx index 97dfdad..dc067c2 100644 --- a/2018-05/ts-react-new-features/src/demo-meetup/app.tsx +++ b/2018-05/ts-react-new-features/src/demo-meetup/app.tsx @@ -21,6 +21,6 @@ export const App = () => ( /> )} - {props => } + {(props) => } ) diff --git a/2018-05/ts-react-new-features/src/provider.tsx b/2018-05/ts-react-new-features/src/provider.tsx index 21e29e0..22570d3 100644 --- a/2018-05/ts-react-new-features/src/provider.tsx +++ b/2018-05/ts-react-new-features/src/provider.tsx @@ -273,7 +273,7 @@ const App1 = () => { * 3. fix A * we can destructure within our function instead in arguments declaration and cast props back to be non optional */ -const ChildCmpFix1: SFC> = props => { +const ChildCmpFix1: SFC> = (props) => { const { who, callMe } = props as Required return ( <>