1. 程式人生 > 程式設計 >TypeScript泛型引數預設型別和新的strict編譯選項

TypeScript泛型引數預設型別和新的strict編譯選項

概述

TypeScript 2.3 增加了對宣告泛型引數預設型別的支援,允許為泛型型別中的型別引數指定預設型別。

接下來看看如何通過泛型引數預設將以下react元件從js(和jsX)遷移到 TypeScript (和TSX):

class Greeting extends react.Component {
  render() {
    return <span>Hello,{this.props.name}!</span>;
  }
}

為元件類建立型別定義

咱們先從為Component類建立型別定義開始。每個基於類的 React 元件都有兩個屬性:props和state,型別定義結構大致如下:

declare namespace React {
  class Component {
    props: any;
    state: any;
  }
}

注意,這個是大大簡化的示例,因為咱們是為了演示泛型型別引數及其預設值的內容。

現在就可以通過繼承來呼叫上面定義的Component:

class Greeting extends React.Component {
  render() {
    return <span>Hello,{this.props.name}!</span>
  }
}

咱們可以如下方式建立元件的例項:

<Greeting name="world" JSWMt
/>

渲染上面元件會生成以下html:

<span>Hello,World!</span>

nice,繼續。

使用泛型型別定義 Props 和 State

雖然上面的示例編譯和執行得很好,但是咱們的 Component 型別定義不是很精確。因為咱們將props和state型別設定為any,所以 TypeScript 編譯器也幫不上什麼忙。

咱們得更具體一點,通過兩種泛型型別:Propwww.cppcns.coms和State,這樣就可以準確地描述props和state屬性的結構。

declare namespace React {
  class Component <Props,State> {
    props: Props;
    state: State;
  }
}

接著建立一個GreetingProps型別,該型別定義一個字串型別name的屬性,並將其作為Props型別引數的型別引數傳遞:

type GreetingProps = { name: string };

class Greeting extends React.Component<GreetingProps,any> {
  render() {
    return <span>Hello,{this.props.name}!</span>;
  }
}

1)GreetingProps是型別引數Props的型別引數

2) 類似地,any是型別引數State的型別引數

有了這些型別,咱們的元件得到更好的型別檢查和自動提示:

TypeScript泛型引數預設型別和新的strict編譯選項

但是,現在使用React.Component類時就必需供兩種型別。咱們開著的初始程式碼示例就不在正確地進行型別檢查:

// Error: 泛型型別 Component<Props,State>
// 需要 2 個型別引數。
class Greeting extends React.Component {
  render() {
    return <span程式設計客棧>Hello,{this.props.name}!</span>;
  }
}

如果咱們不想指定像GreetingProps這樣的型別,可以通過為Props和State型別引數提供any型別來修正程式碼:

class Greeting extends React.Component<any,{this.props.name}!</span>;
  }
}

這種方法可以讓編譯器通過,但咱們還有更優雅的做法:泛型引數預設型別。

泛型引數預設型別

從 TypeScript 2.3 開始,咱們可以為每個泛型型別引數新增一個預設型別。在下面的例子中,如果沒有顯式地給出型別引數,那麼Props和State都都是any型別:

declare namespace React {
  class Component<Props = any,State = any> {
    props: Props;
    state: State;
  }
}

現在,咱們就可以不用指定泛型型別就可以通過編譯器的檢查:

class Greeting extends React.Component {
  render() {
    return <span>Hello,{this.props.name}!</span>;
  }
}

當然,咱們仍然可以顯式地為Props型別引數提供型別並覆蓋預設的any型別,如下所示:

type GreetingProps = { name: string };

class Greeting extends React.Component<GreetingProps,{this.props.name}!</span>;
  }
}

這兩個型別引數現在都有一個預設型別,所以它們是可選的,咱們可以僅為Props指定顯式的型別引數:

type GreetingProps = { name: string };

class Greeting extends React.Component<GreetingProps> {
  render() {
    return <span>Hello,{this.props.name}!</span>;
  }
}

注意,咱們只提供了一個型別引數。但是,被省略可選型別引數前一個必須要指定型別,否則不能省略。

其它事例

在上一篇中關於 TypeScript 2.2 中混合類的文章中,咱們最初聲明瞭以下兩個類型別名:

type constructor<T> = new (...args: any[]) => T;
type constructable = Constructor<{}>;

Constructable型別純粹是語法糖。它可以代替Constructor<{}>型別,這樣就不必每次都要寫泛型型別引數。使用泛型引數預設值,就可以完全去掉附加的可構造型別,並將{}設定為預設型別

type Constructor<T = {}> = new (...args: any[]) => T;

語法稍微複雜一些,但是生成的程式碼更簡潔,Good。

新的--strict主要編譯選項

TypeScript 2.3 引入了一個新的--strict編譯器選項,它支援許多與更嚴格的型別檢查相關的其他編譯器選項。

TypeScript 加入的新檢查項為了避免不相容現有專案通常都是預設關閉的。雖然避免不相容是好事,但這個策略的一個弊端則是使配置最高型別安全越來越複雜,這麼做每次 TypeScript 版本釋出時都需要顯示地加入新選項。有了--strict編譯選項,就可以選擇最高級別的型別安全(瞭解隨著更新版本的編譯器增加了增強的型別檢查特性可能會報新的錯誤)。

新的--strict編譯器選項包含了一些建議配置的型別檢查選項。具體來說,指定--strict相當於是指定了以下所有選項(未來還可能包括更多選項):

  • --strictNullChecks
  • --noImplicitAny
  • --noImplicitThis
  • --alwaysStrict

未來的 TypeScript 版本可能會在這個集合中新增額外的型別檢查選項。這意味著咱們不需要監控每個 TypeScript 版本來獲得應該在專案中啟用的新嚴格性選項。如果向上述選項集添加了新選項,則在升級專案的 TypeScript 版本後,它們將自動啟用。

--strict編譯選項會為以上列出的編譯器選項設定預設值。這意味著還可以單獨控制這些選項。比如:

--strict --noImplicitThis false

或者在tsconfig.json檔案指定:

{
  "strict": true,"alwaysStrict": false
}

這將是開啟除--noImplicitThis編譯選項以外的所有嚴格檢查選項。使用這個方式可以表述除某些明確列出的項以外的所有嚴格檢查項。換句話說,現在可以在預設最高級別的型別安全下排除部分檢查。

改進的--init輸出

除了預設的--strict設定外,tsc --init還改進了輸出。tsc --init預設生成的tsconfig.json檔案現在包含了一些帶描述的被註釋掉的常用編譯器選項. 你可以去掉相關選項的註釋來獲得期望的結果。我們希望新的輸出能簡化新專案的配置並且隨著專案成長保持配置檔案的可讀性。

通過tsc --init編譯器可以為構建一個配置檔案:

$ tsc --init

message TS6071: Successfully created a tsconfig.json file.

執行此命令後,會當前工作目錄中生成一個tsconfig.json檔案,生成的配置如下所示:

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",/* Specify ECMAScript target version: 'ES3' (default),'ES5','ES2015','ES2016','ES2017',or 'ESNEXT'. */
    "module": "commonjs",/* Specify module code generation: 'commonjs','amd','system','umd' or 'es2015'. */
    // "lib": [],/* Specify library files to be included in the compilation:  */
    // "allowJs": true,/* Allow javascript files to be compiled. */
    // "checkJs": true,/* Report errors in .js files. */
    // "jsx": "preserve",/* Specify JSX code generation: 'preserve','react-native',or 'react'. */
    // "declaration": true,/* Generates corresponding '.d.ts' file. */
    // "sourceMap": true,/* Generates corresponding '.map' file. */
    // "outFile": "./",/* Concatenate and emit output to single file. */
    // "outDir": "./",/* Redirect output structure to the directory. */
    // "rootDir": "./",/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "removeComments": true,/* Do not emit comments to output. */
    // "noEmit": true,/* Do not emit outputs. */
    // "importHelpers": true,/* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,/* Provide full support for iterables in 'for-of',spread,and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,/* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true                            /* Enable all strict type-checking options. */
    // "noImplicitAny": true,/* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,/* Enable strict null checks. */
    /程式設計客棧/ "noImplicitThis": true,/* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,/* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,/* Report errors on unused locals. */
    // "noUnusedParameters": true,/* Report errors on unused parameters. */
    // "noImplicitReturns": true,/* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,/* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",/* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",/* Base directory to resolve non-absolute module names. */
    // "paths": {},/* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],/* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],/* List of folders to include type definitions from. */
    // "types": [],/* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,/* Allow default imports from modules with no default export. This does not affect code emit,just typechecking. */

    /* Source Map Options */
    // "sourceRoot": "./",/* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "./",/* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,/* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,/* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,/* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,/* Enables experimental support for emitting type metadata for decorators. */
  }
}

注意--strict是預設啟用的。這意味著在啟動一個新的TypeScript專案時,自動進入預設模式。

--checkJS選項下.js檔案中的錯誤

即便使用了--allowJs,TypeScript 編譯器預設不會報.js檔案中的任何錯誤。TypeScript 2.3 中使用--checkJs選項,.js檔案中的型別檢查錯誤也可以被報出.

你可以通過為它們新增// @ts-nocheck註釋來跳過對某些檔案的檢查,反過來你也可以選擇通過新增// @ts-check註釋只檢查一些.js檔案而不需要設定--checkJs編譯選項。你也可以通過新增//JSWMt @ts-ignore到特定行的一行前來忽略這一行的錯誤.

.js檔案仍然會被檢查確保只有標準的 ECMAScript 特性,型別標註僅在.ts檔案中被允許,在.js中會被標記為錯誤。JSDoc註釋可以用來為你的 JS 程式碼新增某些型別資訊,

以上就是TypeScript泛型引數預設型別和新的strict編譯選項的詳細內容,更多關於TypeScript的資料請關注我們其它相關文章!