TypeScript с каждым релизом становится все круче и интереснее! В последней бета версии(4.4) ребята добавили парочку очень крутых фич (https://devblogs.microsoft.com/typescript/announcing-typescript-4-4-beta/). Вот краткий обзор основных изменений:
Больше всего я заценил
Control Flow Analysis of Aliased Conditions , благодаря этой фичи результат тайпгарда можно сохранить в переменную и дальше в коде использовать эту переменную что бы закастить тип. Если не поняли, вот пример:interface BaseOptions {
prop1: string;
prop2: number;
}
interface ClickableOptions extends BaseOptions {
anchorLabel: string
onAnchorClick: VoidFunction
}
const Component = ({ prop1, prop2, ...props }: BaseOptions | ClickableOptions) => {
const isClickable = 'anchorLabel' in props;
if (isClickable) {
const { onAnchorClick } = props;
}
// ...
const anchorLabel = isClickable ? props.anchorLabel : null;
}Как видите мы можем реюзать
isClickable переменную в разных местах и TS не будет ругаться что в пропах нет anchorLabel и onAnchorClick , ну разве не топчик? 😎 В предыдущих версиях
'anchorLabel' in props приходилось выносить в отдельную тайпгард функцию и вызывать ее, что бы помочь TSу с типами, и это хорошо если тайпгард простой, и особо не влияет на перф. Ну или как альтернативный и не очень красивый вариант без тайпгарда, который уменьшает надежность типов - использовать ключевое слово as :interface BaseOptions {
prop1: string;
prop2: number;
}
interface ClickableOptions extends BaseOptions {
anchorLabel: string
onAnchorClick: VoidFunction
}
const isClickable = (props: Omit<BaseOptions | ClickableOptions, keyof BaseOptions>): props is Omit<ClickableOptions, keyof BaseOptions> => 'anchorLabel' in props
// Good
const Component = ({ prop1, prop2, ...props }: BaseOptions | ClickableOptions) => {
if (isClickable(props)) {
const { onAnchorClick } = props;
}
// ...
const anchorLabel = isClickable(props) ? props.anchorLabel : null;
}
// Bad
const Component = ({ prop1, prop2, ...props }: BaseOptions | ClickableOptions) => {
const isClickable = 'anchorLabel' in props;
if (isClickable) {
const { onAnchorClick } = props as Omit<ClickableOptions, keyof BaseOptions>;
}
// ...
const anchorLabel = isClickable ? (props as Omit<ClickableOptions, keyof BaseOptions>).anchorLabel : null;Также теперь можно использовать символы, оч удивило что раньше TS это не саппортал, и строковые паттерны в качестве ключей объектов, что очень полезно в некоторых кейсах, например затайпать
data атрибуты в React'е стало намного проще:interface Props {
value: string;
[symbols: symbol]: number;
[data: `${'data' | 'aria'}-${string}`]: string;
}
const simple: Props = { value: '' };
const symbols: Props = { value: '', [Symbol('')]: 0 };
const dataAttr: Props = { value: '', "data-opened": 'true', "aria-label": "label" };Ошибки в
catch блоке имеют тип unknown вместо any , что делает код намного безопаснее, т.к. придется делать тайпгарды если нужно достать что-то ( err.message ) из ошибки.Ну и напоследок, появилась возможность сказать TSу что опциональные ключи в объектах являются ТОЛЬКО опциональными и туда нельзя засунуть
undefined . Возможно эта фича покажется вам не такой уж и полезной, но она позволяет избежать таких проблем:interface Entity {
a: number;
b: string;
}
const entity: Entity = {a: 10, b: '20'};
const patch: Partial<Entity> = { a: 10, b: undefined };
const updated: Entity = { ...entity, ...patch }
updated.b.toUpperCase(); // Runtime Error: Cannot read property 'toUpperCase' of undefinedС каждым новым релизом люблю TS все больше ❤️, надеюсь и вы перешли на TS и также кайфуете ✌️
Читать в ноушен: https://bit.ly/384LwZe
#typescript #news