11个技巧让你成为更好的 Typescript 程序员

news2025/4/7 10:13:42

学习 Typescript 通常是一次重新发现之旅。您的最初印象可能非常具有欺骗性:这不就是一种注释 Javascript 的方式,所以编译器可以帮助我找到潜在的错误吗?

通过 r/mevlix@reddit

虽然这句话通常是正确的,但随着您继续前进,您会发现该语言最不可思议的力量在于组合、推断和操纵类型。

本文将总结几个技巧,帮助您充分发挥该语言的潜力。

#1 思考{Set}

类型对于程序员来说是一个日常概念,但要简洁地定义它却出奇地困难。我发现将Set用作概念模型会很有帮助。

例如,新学习者发现 Typescript 的组合类型的方式违反直觉。举个很简单的例子:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Measure</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Style</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">color</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-comment-color)">// typed { radius: number; color: string }</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Measure</span> <span style="color:var(--syntax-error-color)">&</span> <span style="color:var(--syntax-name-color)">Style</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>

如果您&在逻辑 AND 的意义上解释运算符,您可能希望Circle它是一个虚拟类型,因为它是两种类型的结合,没有任何重叠字段。这不是打字稿的工作方式。相反,在Set中思考更容易推断出正确的行为:

  • 每种类型都是一值。
  • 有些集合是无限的:字符串、数字;一些有限的:布尔值,未定义的,......
  • unknown通用集(包括所有值),而never空集(包括无值)。
  • 类型Measure是所有对象的集合,包含一个名为 的数字字段radius。与 相同Style
  • &运算符创建一个IntersectionMeasure & Style表示包含radius和字段的一组对象color,这实际上是一个较小的 Set,但具有更常用的字段。
  • 类似地,|运算符创建一个Union:一个更大的 Set 但可能具有更少的常用字段(如果组合了两个对象类型)。

Set还有助于理解可赋值性:仅当值的类型是目标类型的子集时才允许赋值:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ShapeKind</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">foo</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">getSomeString</span><span style="color:var(--syntax-text-color)">();</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">ShapeKind</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// disallowed because string is not subset of ShapeKind</span>
<span style="color:var(--syntax-name-color)">shape</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">foo</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// allowed because ShapeKind is subset of string</span>
<span style="color:var(--syntax-name-color)">foo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>

以下文章对 Set 中的思维方式进行了出色的详尽介绍。

TypeScript 和集合论 | 伊万·奥韦耶罗

集合论如何帮助理解 TypeScript 中的类型可分配性和解析度?

ivov.dev

#2 理解声明的类型和缩小的类型

一个极其强大的打字稿功能是基于控制流的自动类型缩小。这意味着变量在代码位置的任何特定点都有两种类型与之关联:声明类型和缩小类型。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">foo</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">x</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">x</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">string</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// x's type is narrowed to string, so .length is valid</span>
    <span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">x</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span><span style="color:var(--syntax-text-color)">);</span>

    <span style="color:var(--syntax-comment-color)">// assignment respects declaration type, not narrowed type</span>
    <span style="color:var(--syntax-name-color)">x</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">x</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// disallowed because x is now number</span>
    <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">else</span> <span style="color:var(--syntax-text-color)">{</span>
        <span style="color:var(--syntax-text-color)">...</span>
    <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

#3 使用有区别的联合而不是可选字段

在定义一组像 Shape 这样的多态类型时,很容易从以下开始:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Shape</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">radius</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">width</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">height</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getArea</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">?</span> 
    <span style="color:var(--syntax-text-color)">Math</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">PI</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-error-color)">!</span> <span style="color:var(--syntax-error-color)">**</span> <span style="color:var(--syntax-literal-color)">2</span>
    <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">width</span><span style="color:var(--syntax-error-color)">!</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">height</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

非空断言(访问radiuswidth和字段时)是必需的,因为与其他字段height之间没有建立关系。kind相反,discriminated union 是一个更好的解决方案:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Rect</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">width</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">height</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Shape</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-name-color)">Rect</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getArea</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">?</span> 
        <span style="color:var(--syntax-text-color)">Math</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">PI</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">radius</span> <span style="color:var(--syntax-error-color)">**</span> <span style="color:var(--syntax-literal-color)">2</span>
        <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">width</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">height</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

类型缩小消除了强制转换的需要。

#4 使用类型谓词来避免类型断言

如果你以正确的方式使用打字稿,你应该很少会发现自己使用显式类型断言(比如value as SomeType);但是,有时您仍然会感到冲动,例如:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Rect</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">width</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">height</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Shape</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-name-color)">Rect</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">isCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">isRect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">myShapes</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">[]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">getShapes</span><span style="color:var(--syntax-text-color)">();</span>

<span style="color:var(--syntax-comment-color)">// error because typescript doesn't know the filtering</span>
<span style="color:var(--syntax-comment-color)">// narrows typing</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circles</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Circle</span><span style="color:var(--syntax-text-color)">[]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">myShapes</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">filter</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">isCircle</span><span style="color:var(--syntax-text-color)">);</span>

<span style="color:var(--syntax-comment-color)">// you may be inclined to add an assertion:</span>
<span style="color:var(--syntax-comment-color)">// const circles = myShapes.filter(isCircle) as Circle[];</span>
</code></span></span>

一个更优雅的解决方案是改为更改isCircleisRect返回类型谓词,这样它们可以帮助 Typescript 在调用后进一步缩小类型范围filter

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">isCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">):</span> <span style="color:var(--syntax-name-color)">shape</span> <span style="color:var(--syntax-declaration-color)">is</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">isRect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">):</span> <span style="color:var(--syntax-name-color)">shape</span> <span style="color:var(--syntax-declaration-color)">is</span> <span style="color:var(--syntax-name-color)">Rect</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-text-color)">...</span>
<span style="color:var(--syntax-comment-color)">// now you get Circle[] type inferred correctly</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circles</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">myShapes</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">filter</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">isCircle</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>

#5 控制联合类型的分布方式

类型推断是 Typescript 的本能;大多数时候,它会默默地为你工作。但是,您可能需要对含糊不清的细微情况进行干预。分布式条件类型就是其中一种情况。

假设我们有一个ToArray辅助类型,如果输入类型还不是一个,它会返回一个数组类型:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ToArray</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">T</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-text-color)">Array</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">unknown</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-text-color)">?</span> <span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">[];</span>
</code></span></span>

对于以下类型,您认为应该推断出什么?

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Foo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">ToArray</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-error-color)">|</span><span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>

答案是string[] | number[]。但这是模棱两可的。为什么不(string | number)[]呢?

默认情况下,当 typescript 遇到string | number泛型参数(T此处)的联合类型(此处)时,它会分配到每个成分中,这就是您得到string[] | number[]. 这种行为可以通过使用特殊语法并包装T在一对 中来改变[],例如:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ToArray</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-text-color)">Array</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">unknown</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-text-color)">?</span> <span style="color:var(--syntax-name-color)">T</span> <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">[];</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Foo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">ToArray</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>

NowFoo被推断为 type (string | number)[]

#6 在编译时使用详尽检查来捕获未处理的情况

当对枚举进行 switch-casing 时,一个好习惯是主动为不期望的情况犯错,而不是像在其他编程语言中那样默默地忽略它们:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getArea</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">switch</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">case</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">Math</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">PI</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">radius</span> <span style="color:var(--syntax-error-color)">**</span> <span style="color:var(--syntax-literal-color)">2</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-declaration-color)">case</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">width</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">height</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">default</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-declaration-color)">throw</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-text-color)">Error</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">Unknown shape kind</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

使用 Typescript,您可以让静态类型检查通过使用以下never类型更早地为您找到错误:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getArea</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Shape</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">switch</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">case</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">Math</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">PI</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">radius</span> <span style="color:var(--syntax-error-color)">**</span> <span style="color:var(--syntax-literal-color)">2</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-declaration-color)">case</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">width</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">height</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">default</span><span style="color:var(--syntax-text-color)">:</span>
      <span style="color:var(--syntax-comment-color)">// you'll get a type-checking error below          </span>
      <span style="color:var(--syntax-comment-color)">// if any shape.kind is not handled above</span>
      <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">_exhaustiveCheck</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">never</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">;</span>
      <span style="color:var(--syntax-declaration-color)">throw</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-text-color)">Error</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">Unknown shape kind</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

有了这个,就不可能getArea在添加新的形状种类时忘记更新函数。

该技术背后的基本原理是该never类型不能分配任何东西,除了nevershape.kind如果case 语句穷尽了所有候选者,则唯一可能到达的类型default是 never;但是,如果任何候选人未被涵盖,它将泄漏到default分支并导致无效分配。

type#7更 喜欢interface

在打字稿中,当用于键入对象时type,它们是非常相似的结构。尽管可能存在争议,但我的建议是在大多数情况下interface始终使用,并且仅在满足以下任一条件时才使用:typeinterface

  • 您想要利用 的“合并”功能interface

  • 您有涉及类/接口层次结构的 OO 样式代码。

否则,始终使用更通用的type构造会产生更一致的代码。

#8 在适当的时候优先使用元组而不是数组

对象类型是输入结构化数据的常用方式,但有时您可能需要更简洁的表示方式,而是使用简单的数组。例如,我们Circle可以这样定义:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">)[];</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-literal-color)">1.0</span><span style="color:var(--syntax-text-color)">];</span>  <span style="color:var(--syntax-comment-color)">// [kind, radius]</span>
</code></span></span>

但是这种输入不必要地松散,您可以通过创建类似['circle', '1.0']. 我们可以通过使用 Tuple 来使其更严格:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">];</span>

<span style="color:var(--syntax-comment-color)">// you'll get an error below</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">1.0</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">];</span>
</code></span></span>

元组用法的一个很好的例子是 React 的useState.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setName</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">''</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>

它既紧凑又类型安全。

#9 控制推断类型的一般性或具体性

Typescript 在进行类型推断时使用合理的默认行为,旨在简化常见情况下的代码编写(因此类型不需要显式注释)。有几种方法可以调整它的行为。

  • 用于const缩小到最具体的类型
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">foo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">foo</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">};</span> <span style="color:var(--syntax-comment-color)">// typed: { name: string }</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">Bar</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">bar</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">const</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">// typed: { name: 'bar' }</span>

<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">a</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-literal-color)">2</span><span style="color:var(--syntax-text-color)">];</span> <span style="color:var(--syntax-comment-color)">// typed: number[]</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">b</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-literal-color)">2</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">const</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">// typed: [1, 2]</span>

<span style="color:var(--syntax-comment-color)">// typed { kind: 'circle; radius: number }</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">const</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1.0</span> <span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-comment-color)">// the following won't work if circle wasn't initialized</span>
<span style="color:var(--syntax-comment-color)">// with the const keyword</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">shape</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-text-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">rect</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>
  • 用于satisfies检查类型而不影响推断类型

考虑以下示例:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">NamedCircle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">name</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">NamedCircle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1.0</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">yeah</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-comment-color)">// error because circle.name can be undefined</span>
<span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>

我们得到一个错误,因为根据circle的声明类型NamedCirclename字段确实可以是未定义的,即使变量初始值设定项提供了一个字符串值。当然,我们可以删除类型注释,但我们将放弃对对象: NamedCircle有效性的类型检查。circle相当进退两难。

幸运的是,Typescript 4.9 引入了一个新satisfies关键字,它允许您在不改变推断类型的情况下检查类型:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">NamedCircle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">name</span><span style="color:var(--syntax-text-color)">?:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-comment-color)">// error because radius violates NamedCircle</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">wrongCircle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">1.0</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">ha</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-name-color)">satisfies</span> <span style="color:var(--syntax-name-color)">NamedCircle</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">circle</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1.0</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">yeah</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-name-color)">satisfies</span> <span style="color:var(--syntax-name-color)">NamedCircle</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// circle.name can't be undefined now</span>
<span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>

修改后的版本享有两个好处:保证对象文字符合NamedCircle类型,并且推断类型具有不可为空的name字段。

#10infer用于创建额外的泛型类型参数

在设计实用函数和类型时,您经常会觉得需要使用从给定类型参数中提取的类型。在这种情况下,infer关键字就派上用场了。它可以帮助您即时推断出新的类型参数。这里有两个简单的例子:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// gets the unwrapped type out of a Promise;</span>
<span style="color:var(--syntax-comment-color)">// idempotent if T is not Promise</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ResolvedPromise</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">T</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-text-color)">Promise</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">infer</span> <span style="color:var(--syntax-name-color)">U</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-text-color)">?</span> <span style="color:var(--syntax-name-color)">U</span> <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">t</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">ResolvedPromise</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-text-color)">Promise</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-error-color)">>></span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">// t: string</span>

<span style="color:var(--syntax-comment-color)">// gets the flattened type of array T;</span>
<span style="color:var(--syntax-comment-color)">// idempotent if T is not array</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Flatten</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">T</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-text-color)">Array</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">infer</span> <span style="color:var(--syntax-name-color)">E</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-text-color)">?</span> <span style="color:var(--syntax-name-color)">Flatten</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">E</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">T</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">e</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Flatten</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">[][]</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">// e: number</span>
</code></span></span>

infer关键字的工作原理可以T extends Promise<infer U>理解为:假设 T 与某些实例化的通用 Promise 类型兼容,即兴创作一个类型参数 U 使其工作。因此,如果T被实例化为Promise<string>,则 的解U将是string

#11通过在类型操作上发挥创意来 保持DRY

Typescript 提供了强大的类型操作语法和一组非常有用的实用程序,可帮助您将代码重复减少到最低限度。这里只是一些特别的例子:

  • 而不是复制字段声明:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">User</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">age</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">gender</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">country</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">city</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span>
<span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Demographic</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">age</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">number</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">gender</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Geo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">country</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">city</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

,使用Pick实用程序提取新类型:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">User</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">age</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">gender</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">country</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">city</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span>
<span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Demographic</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">Pick</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">User</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">age</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-error-color)">|</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">gender</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Geo</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">Pick</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">User</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">country</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-error-color)">|</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">city</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>
  • 而不是复制函数的返回类型
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">createCircle</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span>
        <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">const</span><span style="color:var(--syntax-text-color)">,</span>
        <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1.0</span>
    <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">transformCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-text-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-text-color)">...</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-name-color)">transformCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">createCircle</span><span style="color:var(--syntax-text-color)">());</span>
</code></span></span>

,用于ReturnType<T>提取它:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">createCircle</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span>
        <span style="color:var(--syntax-name-color)">kind</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">circle</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">const</span><span style="color:var(--syntax-text-color)">,</span>
        <span style="color:var(--syntax-name-color)">radius</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1.0</span>
    <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">transformCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">circle</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">ReturnType</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">createCircle</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-text-color)">...</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-name-color)">transformCircle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">createCircle</span><span style="color:var(--syntax-text-color)">());</span>
</code></span></span>
  • 而不是并行同步两种类型的形状(此处为 typeof config 和 Factory):
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ContentTypes</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">news</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">video</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// config for indicating what content types are enabled</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">config</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">news</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">video</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">false</span> <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-name-color)">satisfies</span> <span style="color:var(--syntax-text-color)">Record</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">ContentTypes</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">boolean</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// factory for creating contents</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Factory</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">createNews</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">Content</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">createBlog</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">Content</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

,使用Mapped Type和Template Literal Type根据配置的形状自动推断出正确的工厂类型:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ContentTypes</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">news</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-error-color)">|</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">video</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-comment-color)">// generic factory type with a inferred list of methods</span>
<span style="color:var(--syntax-comment-color)">// based on the shape of the given Config</span>
<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">ContentFactory</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">Config</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-text-color)">Record</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">ContentTypes</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">boolean</span><span style="color:var(--syntax-error-color)">>></span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">k</span> <span style="color:var(--syntax-declaration-color)">in</span> <span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-error-color)">&</span> <span style="color:var(--syntax-declaration-color)">keyof</span> <span style="color:var(--syntax-name-color)">Config</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">Config</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">k</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-declaration-color)">true</span>
        <span style="color:var(--syntax-text-color)">?</span> <span style="color:var(--syntax-string-color)">`create</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">Capitalize</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">k</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span>
        <span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">never</span><span style="color:var(--syntax-text-color)">]:</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">Content</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-comment-color)">// config for indicating what content types are enabled</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">config</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">news</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">video</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">false</span> <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-name-color)">satisfies</span> <span style="color:var(--syntax-text-color)">Record</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">ContentTypes</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">boolean</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Factory</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">ContentFactory</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">config</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-comment-color)">// Factory: {</span>
<span style="color:var(--syntax-comment-color)">//     createNews: () => Content;</span>
<span style="color:var(--syntax-comment-color)">//     createBlog: () => Content; </span>
<span style="color:var(--syntax-comment-color)">// }</span>
</code></span></span>

发挥您的想象力,您会发现无限的探索潜力。

包起来

这篇文章涵盖了 Typescript 语言中的一组相对高级的主题。实际上,您可能会发现直接应用它们并不常见;然而,此类技术被专门为 Typescript 设计的库大量使用:如Prisma和tRPC。了解这些技巧可以帮助您更好地了解这些工具如何在幕后发挥其魔力。


PS 我们正在构建ZenStack — 一个用于使用 Next.js + Typescript 构建安全 CRUD 应用程序的工具包。我们的目标是让您节省编写样板代码的时间,并专注于构建重要的东西——用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/117712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【聆思CSK6 视觉AI开发套件试用】AI识别试用以及闭坑方案

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;X Y Z 非常感谢能有这次机会体验聆思CSK6 视觉AI开发套件。上班的一大早收到了快递&#xff0c;迫不及待的打开快递。必须先来个图&#xff0…

4个技巧,节约网络工程师一半的时间

01 批量ping网段 对于一个网段ip地址众多&#xff0c;如果单个检测实在麻烦&#xff0c;那么你就可以直接批量ping网段检测&#xff0c;那个ip地址出了问题&#xff0c;一目了然。 先看代码&#xff0c;直接在命令行窗口输入&#xff1a; for /L %D in (1,1,255) do ping 10…

渗透测试神器--Burp Suite

一、介绍 Burp Suite 是用于攻击web 应用程序的集成平台。Burp Suite是一款信息安全从业人员必备的集成型的渗透测试工具&#xff0c;它采用自动测试和半自动测试的方式&#xff0c;包含了Proxy、Spider、Scanner、Intruder、Repeater、Sequencer、Decoder、Comparer等工具模块…

uniapp 窗口小工具、桌面小部件、微件 Ba-AppWidget

简介&#xff08;下载地址&#xff09; Ba-AppWidget 是一款窗口小工具&#xff08;桌面小部件、微件&#xff09;插件&#xff0c;默认为音乐播放器的样式&#xff0c;有其他界面需要&#xff0c;可联系作者定制。 支持点击事件监听支持动态更改页面内容支持设置小工具的预览…

区块链(一): 以太坊基础知识

目录什么是区块链&#xff1f;什么是以太坊&#xff1f;什么是加密货币&#xff1f;以太坊与比特币有什么不同&#xff1f;以太坊能做什么&#xff1f;什么是智能合约&#xff1f;以太坊社区以太坊白皮书什么是区块链&#xff1f; 区块链是一个交易数据库&#xff0c;在网络中…

容器,容器技术,云容器相关入门知识

前言 最近面试了一家国企&#xff0c;交谈愉快&#xff0c;对方的工程师问到容器时&#xff0c;突然愣了一下。脑子里有学习前端时候学习的docker&#xff0c;但印象里docker可不能代表容器技术&#xff0c;于是学习容器相关知识后整理相关知识以作巩固。 什么是容器 有点开…

SuperMap iDesktop/iDesktopX 端性能优化

作者&#xff1a;yd&hyy 一、背景 在使用iDesktop/iDesktopX的三维场景加载GIS数据的过程中&#xff0c;随着数据的种类、大小、数量的增多&#xff0c;往往会有很多的性能问题&#xff0c;加载速率缓慢&#xff0c;数据显示清晰度不足&#xff0c;多数据交叠显示错误&am…

『分分钟玩转VueRouter●上』VueRouter的一些基础配置

文章目录前言一、vue中如何使用VueRouter?二、路由使用的基本配置1.多级路由配置2.路由中的query参数3.命名路由4.路由的params参数5.路由的props配置6.router-link的replace属性7.通配符路由前言 计算机网络中有一个路由的概念&#xff1a;路由是指网络数据包发送到目的地址的…

php宝塔搭建部署实战SDCMS蓝色通用宽屏企业网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的SDCMS蓝色通用宽屏企业网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&…

maven 继承和聚合的区别

maven 继承和聚合的区别 参考 https://cloud.tencent.com/developer/article/1397748 继承 目的&#xff1a;统一管理version版本&#xff0c;少写冗余代码。使用&#xff1a; 父类pom不写业务&#xff0c;只写 pom的jar包版本等信息&#xff0c;子类中使用 parent 标签&…

STM32G473CBT6关于ADC采集的总结

STM32G473CBT6单片机在浮点运算&#xff0c;信号采集、数据处理方面有很大的用途。因相关的资料较少&#xff0c;特此做一下笔记&#xff0c;方便后期使用。STM32CubeMX软件比较强大&#xff0c;兼容IAR和keil方便直接生成代码文件&#xff0c;但相关的库不熟悉&#xff0c;好东…

【Web安全】应用层拒绝服务攻击

目录 1、DDOS简介 &#xff12;、应用层DDOS 2.1 &#xff23;&#xff23;攻击 2.2 限制请求频率 2.3 道高一尺&#xff0c;魔高一丈 3、验证码 &#xff23;&#xff21;&#xff30;&#xff34;&#xff23;&#xff28;&#xff21; 4、防御应用层DDOS 5、资源…

章节五:RASA NLU组件介绍--语言模型和分词器

​ 这里写目录标题一、前言二、语言模型组件1、MitieNLP2、SpacyNLP三、分词器1、WhitespaceTokenizer2、JiebaTokenizer3、MitieTokenizer4、SpacyTokenizer5、自定义分词器一、前言 RASA在处理对话时&#xff0c;整体流程是pipeline结构&#xff0c;自然语言理解&#xff08…

【漏洞分析】Apache ShardingSphere-Proxy <5.3.0 身份认证绕过

漏洞简介 2022年12月22日&#xff0c;Apache 官方公告发布 ShardingSphere-Proxy 5.3.0 之前版本存在身份绕过漏洞&#xff08;CVE-2022-45347&#xff09;。当 ShardingSphere-Proxy 使用 MySQL 作为后端数据库时&#xff0c;由于 ShardingSphere-Proxy 在客户端认证失败后没…

Linux-脚本安装jdk(使用jdk压缩包方式)

1、下载Linux版jdk oracle官网:Java Downloads | Oracle 2、上传jdk到linux 在linux中软件一般安装到/usr/local目录中 3、将jdk解压 解压命令: tar -zxvf jdk-8u301-linux-x64.tar.gz 将解压后的jdk改名为jdk8 mv jdk1.8.0_301 jdk8 4、配置jdk环境变量 使用vi打开/etc/p…

Java 面试题 (六) --------- 框架相关

1、什么是 Spring 框架&#xff1f;Spring 框架有哪些主要模块&#xff1f; Spring是一个控制反转和面向切面的容器框架。 Spring有七大功能模块&#xff1a; 1、Core Core模块是Spring的核心类库&#xff0c;Core实现了IOC功能。 2、AOP Apring AOP模块是Spring的AOP库&…

FLTK的UI设计工具FLUID使用方法总结

tags: FLTK C GUI 写在前面 终于又捡起来FLTK了, 先来看看怎么通过FLUID创建一个图形界面并完成回调函数的创建, 参考的是官方教程中关于创建一个CubeView程序的例子, 教程里面很多都与最新版本的FLTK界面不太一致, 但是通过我的摸索还是找出了方法. 下面来分享一下. 创建类…

centos7搭建mysql5.6

检查是否安装mysql rpm -qa | grep mysql 检查已安装的Mariadb rpm -qa | grep -i mariadb 卸载已安装的Mariadb数据库 rpm -qa | grep mariadb | xargs rpm -e --nodeps 下载mysql5.6安装包文件 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm安…

详解什么是Polygon跨链桥| Tokenview

Polygon是一个Layer2网络&#xff0c;用于解决以太坊的吞吐量和主权挑战。尽管以太坊是最受欢迎的区块链开发平台&#xff0c;但它的吞吐量很低&#xff0c;不适合某些应用程序。Polygon提供特定于应用程序的、与以太坊兼容的侧链&#xff0c;将独立链的可扩展性和独立性与以太…

自学开发技术,从入门到入行

今天我们不谈技术&#xff0c;也不聊业务&#xff0c;说说学习技术的心得。 说到学习这种事情&#xff0c;无论是学什么&#xff0c;都需要持之以恒&#xff0c;拥有坚持的决心才有可能会学到一些东西。如果只是三天打鱼&#xff0c;两天晒网的态度&#xff0c;不出差错的话&a…