Last active
November 5, 2020 12:52
-
-
Save dmitriy-novikov/f27bfdd23fe0bf2188b221c255b9e963 to your computer and use it in GitHub Desktop.
Action Type Inference
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as actions from 'action-creators'; | |
// Тип, который берет action-creators, выводит типы всех экшенов по отдельности и собирает их в union | |
type InferValueTypes<T> = T extends { [key: string]: infer U } | |
? U | |
: never; | |
type ActionTypes = ReturnType<InferValueTypes<typeof actions>>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Примеры кода из разных частей презентации | |
// Numeric Literal Type | |
type onlyNumberOne = 1 | |
const a:onlyNumberOne = 1; | |
const b:onlyNumberOne = 2; // error | |
// String Literal Type | |
type onlyFoo = 'foo' | |
const a:onlyFoo = 'foo'; | |
const b:onlyFoo = 'bar'; //error | |
// Generic | |
function returnTheSame<T>(arg: T): T { | |
return arg; | |
} | |
// Extends | |
function inferLiteralFromString<T extends string>(arg: T): T { | |
return arg; | |
} | |
const a = inferLiteralFromString<string>('some string'); // string | |
const b = inferLiteralFromString<'some string'>('some string'); // 'some string' | |
const c = inferLiteralFromString<number>(100500); //error | |
// Mapped type | |
type Keys = 'option1' | 'option2'; | |
type Flags = { [K in Keys]: boolean }; | |
type mapOfBool = { [key: string]: boolean }; | |
// Conditional type | |
type onlyString<T> = T extends string ? string : never | |
const a:onlyString<string> = 'some string'; // string | |
const b:onlyString<'some string'> = 'some string'; // string | |
const c:onlyString<number> = 42; // error | |
// Infer | |
type Foo<T> = T extends { a: infer U, b: infer U } ? U : never; | |
type T1 = Foo<{ a: string, b: string }>; // string | |
type T2 = Foo<{ a: string, b: number }>; // string | number |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Более универсальный вариант сохранения литерального типа, чем string-literal-simple.ts | |
function inferLiteral<U, T extends U>(arg: T): T { | |
return arg; | |
} | |
function inferStringLiteral<T extends string>(arg: T): T { | |
return inferLiteral<string, T>(arg); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// В Typescript 3.4 можно использовать const assertion прямо в экшенах, без функций для сохранения литерального типа | |
const actionCreator1 = () => ({ | |
type: 'action_with_foo', | |
foo: 'some_value' | |
} as const); | |
const actionCreator2 = () => (<const>{ | |
type: 'action_with_bar', | |
bar: 100500 | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Простая версия функции, которая сохраняет string literal | |
function inferLiteralFromString<T extends string>(arg: T): T { | |
return arg; | |
} | |
// И пример ее использования | |
const actionCreator1 = () => ({ | |
type: inferLiteralFromString( 'action_with_foo'), | |
foo: 'some_value' | |
}); | |
const actionCreator2 = () => ({ | |
type: inferLiteralFromString('action_with_bar'), | |
bar: 100500 | |
}); | |
type ActionTypes = ReturnType<typeof actionCreator1> | ReturnType<typeof actionCreator2>; | |
const reducer = (state, action: ActionTypes) => { | |
switch (action.type) { | |
case 'action_with_bar': | |
return {...state, bar: action.bar }; | |
case 'action_with_foo': | |
return {...state, foo: action.foo }; | |
default: | |
return state; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Подскажи плз откуда в T extends { [key: string]: infer U } берется U type ?