Tommy's blog

developer、popper、喜新恋旧

图片来自《Peaky Blinders》

ReturnType<T>

Challenge Readme

构造一种由函数类型的返回类型组成的类型。不使用内置 ReturnType

1
type MyReturnType<T> = T extends (...args: never[]) => infer A ? A : never;

核心知识点:元组展开 ... 泛型推断 infer 条件类型 extends

注意点

这里需要注意条件类型的参数,当参数为 ...args: unknown[] 时,表示“未知”的类型。

1
2
const fn1 = (v: boolean, w: any) => (v ? 1 : 2);
type fn1ReturnType = MyReturnType<typeof fn1>;

对于函数 fn1,它的参数类型不符合这个签名,因为它的参数类型不是 unknown[],而是具体的 booleanany 类型。此时条件类型 T extends (...args: unknown[]) => infer A 不会匹配到 fn1,因此 fn1Type 的类型将是 never。

提问:never 作为一个底部类型,应该不能赋予除了 never 意外的其他类型,为什么能命中 true 分支?
导致这个结果的原因是因为,never 任何类型的 subType

1
2
type Check<T> = never extends T ? true : false;
type result = check<xxx>; // 结果始终为true

T extends (...args: never[]) => infer A 这意味着它是一个接受空参数列表的函数类型。由于 never 类型是空集合的子类型,因此任何具有参数的函数类型也可以被赋值给 (...args: never[]) => infer A。这就解释了为什么条件类型的结果为 true

值得一提的是:

  1. 不相交类型的 inteserction 结果为 never:
1
type result = 1 & 2; // 结果为never
  1. 除了 never,没有其他类型是 never 的 subtype
1
2
type Check<T> = never extends never ? false : T extends never ? true : false;
type result = check<xxx>; // 结果始终为false
  1. 布尔运算
1
2
T | never; // 结果为T
T & never; // 结果为never
  1. 是任何类型的 subtype(上文已通过例子说明)
阅读全文 »

所有挑战来源type-challenges题库。

本节条件判断均使用Equal来验证,副验证Expect

代码如下:

1
2
3
4
5
6
7
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false;

type Expect<T extends true> = T;

在 ts 中,泛型函数的条件判断可以用类型推断来比较两个类型。Equal在提供的类型验证中,使用了两个泛型函数,它们都是立即执行函数。
在这些函数中,通过使用条件类型 <T>() => T extends X ? 1 : 2 和 <T>() => T extends Y ? 1 : 2 对类型 X 和 Y 进行检查。

这里的 1 和 2 实际上是两个不同的类型分支标识符。当条件 <T>() => T extends X ? 1 : 2 成立时,返回 1,表示类型 X 和当前泛型 T 匹配,比较类型 Y 的逻辑与之类似,然后利用 extends 条件类型关键字进行类型推断,如果类型 X 和 Y 匹配,则返回 true,否则返回 false。

知道了这两个条件判断,就可以通过类型推断来验证类型是否匹配,接下来进入正题。

阅读全文 »

第一部分,让我们从构建工具的角度,逐步深入了解 Vite,重点关注它的核心特性——依赖预构建。

理解 vite

Vite 是一个思维比较前卫而且先进的构建工具,它解决了一些Webpack解决不了的问题,同时降低了一些心智负担。
Vite基于自己得天独厚的优势,他已经占有一席之地,Vite是 vue 团队的官方出品,背靠强大的生态,vue-cli已经将Vite作为预设构建工具。使用vue-cli去构建 vue 项目的时候你要写的vue.config.js不再是webpack的配置而是vite的配置(目前只基于浏览器项目)。
Vite支持直接构建reactangular,和svelte项目。
而这只是Vite优势的一角。

阅读全文 »

在之前公司有做过国际化,但是并非自己搭建 ,如果你也没有相关经验且需要对日期插件支持,这篇文章应该对你有用。

实现方式

Vue3中实现国际化(i18n)大概分两种方式:

  1. 使用Vue I18n插件:Vue I18n是一个官方支持的国际化插件,它提供了一种在Vue应用程序中轻松管理多语言的方式。您可以通过安装并导入Vue I18n库,然后在Vue应用程序的入口文件中创建一个I18n实例,并使用各种功能和选项来定义翻译消息、语言环境和翻译规则等。
  2. 自立更生:官方给我们提供了两个不错的思路,一是使用全局变量的方式,二则是利用Provide/inject

由于自立更生式实现复杂翻译(变量翻译和某些需要在翻译文本里插入参数)过于繁琐,所以我选择使用Vue I18n插件。

阅读全文 »

在Angular组件封装中,组件样式难免会遇到被第三方样式覆盖的问题,不可能一直用 !important 来提升样式优先级,如果不加 :host 样式可能会向父节点穿透而覆盖其他组件样式,所以尽量避免使用 !important ,本文介绍Angular组件封装的几种方式。

先了解下ShadowDom

关于ShadowDom简而言之,能使我们将Scoped Styles应用于封装元素,而不会影响其他元素。

ViewEncapsulation Types

Mode Value Description
Emulated 0 通过向宿主元素添加包含替代 ID 的属性并预处理通过 styles 或 styleUrls 提供样式规则,来模拟 Native 所有选择器。这是默认选项。
None 2 不要提供任何模板或样式封装。
ShadowDom 3 使用 Shadow DOM 封装样式。

现在我们一个一个地查看所有ViewEncapsulation模式。

阅读全文 »
0%