TypeScript Deep Dive 日本語版
  • TypeScript Deep Dive 日本語版
  • TypeScript入門 & 環境構築
    • なぜTypeScriptを使うのか?
  • JavaScript
    • 等価演算子の同一性
    • リファレンス
    • nullとundefined
    • this
    • クロージャ
    • Number型
    • Truthy
  • モダンなJavaScriptの機能
    • クラス
      • Classes Emit
    • アロー関数
    • 残余引数(Restパラメータ)
    • let
    • const
    • 分割代入
    • スプレッド演算子
    • for...of
    • Iterator
    • テンプレートリテラル
    • Promise
    • ジェネレータ
    • async await
  • プロジェクトの環境設定
    • コンパイルコンテキスト
      • tsconfig.json
      • コンパイル対象ファイルの設定
    • 宣言空間
    • ファイルモジュール
      • ファイルモジュールの詳細
      • global.d.ts
    • 名前空間
    • 動的インポート
  • Node.js & TypeScriptのプロジェクト作成
  • React & TypeScriptのプロジェクト作成
  • TypeScriptの型システム
    • JavaScriptからの移行ガイド
    • @types パッケージ (DefinitelyTyped)
    • アンビエント宣言(declare)
      • 型定義ファイル
      • グローバル変数の宣言
    • インターフェース
    • Enum
    • lib.d.ts
    • 関数の型
    • 呼び出し可能オブジェクト
    • Type Assertion(型アサーション)
    • Freshness
    • 型ガード
    • リテラル型
    • Readonly
    • ジェネリック型
    • 型推論
    • 型の互換性
    • never
    • 判別可能なUnion型
    • Index signature(インデックス型)
    • 型の移動
    • 例外のハンドリング
    • ミックスイン
  • JSX
    • React
    • React以外のJSX
  • オプション
    • noImplicitAny
    • strictNullChecks
  • TypeScriptのエラー
    • エラーの理解
    • 一般的なエラー
  • NPM
  • テスト
    • Jest
    • Cypress
  • ツール
    • Prettier
    • Husky
    • Changelog
  • その他のヒント
    • String Based Enums
    • Nominal Typing
    • Stateful Functions
    • Bind is Bad
    • Currying
    • Type Instantiation
    • Lazy Object Literal Initialization
    • Classes are Useful
    • Avoid Export Default
    • Limit Property Setters
    • outFile caution
    • JQuery tips
    • static constructors
    • singleton pattern
    • Function parameters
    • Build Toggles
    • Barrel
    • Create Arrays
    • Typesafe Event Emitter
  • スタイルガイド(コーディング規約)
  • TypeScriptコンパイラの内側
    • Program
    • AST
      • TIP: Visit Children
      • TIP: SyntaxKind enum
      • Trivia
    • Scanner
    • Parser
      • Parser Functions
    • Binder
      • Binder Functions
      • Binder Declarations
      • Binder Container
      • Binder SymbolTable
      • Binder Error Reporting
    • Checker
      • Checker Diagnostics
      • Checker Error Reporting
    • Emitter
      • Emitter Functions
      • Emitter SourceMaps
    • Contributing
GitBook提供
このページ内
  • 変数の定義(Variable Definition)
  • 関数の戻り値の型(Function Return Types)
  • 代入(Assignment)
  • 構造化(Structuring)
  • 分解(Destructuring)
  • Type Guard (Type Guards)
  • 警告(Warnings)
  • パラメータに注意してください
  • returnに注意してください
  • noImplicitAny

役に立ちましたか?

  1. TypeScriptの型システム

型推論

TypeScriptは、いくつかの簡単なルールに基づいて変数の型を推論(およびチェック)します。これらのルールはシンプルなので、安全/安全でないコードを認識するために、脳に記憶することができます(これは私と私のチームメイトでは非常にすぐでした)。

型の流れは、私が頭の中で想像する型情報の流れとちょうど一致しています

変数の定義(Variable Definition)

変数の型は、定義によって推論されます。

let foo = 123; // foo is a `number`
let bar = "Hello"; // bar is a `string`
foo = bar; // Error: cannot assign `string` to a `number`

これは右から左に流れる型の例です。

関数の戻り値の型(Function Return Types)

戻り値の型は、return文によって推測されます。次の関数はnumberを返すと推測されます。

function add(a: number, b: number) {
    return a + b;
}

これは底から流れ出ていく型の例です。

代入(Assignment)

関数のパラメータ/戻り値の型は、代入によっても推論することができます。fooはAdderで、numberはaと bの型になります。

type Adder = (a: number, b: number) => number;
let foo: Adder = (a, b) => a + b;

この事実は、以下のコードで示すことができます。あなたが期待する通りのエラーが発生します:

type Adder = (a: number, b: number) => number;
let foo: Adder = (a, b) => {
    a = "hello"; // Error: cannot assign `string` to a `number`
    return a + b;
}

これは、左から右に流れる型の例です。

コールバック引数の関数を作成する場合、同じ代入スタイルの型推論が機能します。結局のところ、argument -> parameterは単に変数代入の一種です。

type Adder = (a: number, b: number) => number;
function iTakeAnAdder(adder: Adder) {
    return adder(1, 2);
}
iTakeAnAdder((a, b) => {
    // a = "hello"; // Would Error: cannot assign `string` to a `number`
    return a + b;
})

構造化(Structuring)

これらの単純なルールは、構造化(オブジェクトリテラルの作成)の下でも機能します。たとえば、次のような場合、fooの型は{a:number, b:number}と推論されます。

let foo = {
    a: 123,
    b: 456
};
// foo.a = "hello"; // Would Error: cannot assign `string` to a `number`

同様に配列について:

const bar = [1,2,3];
// bar[0] = "hello"; // Would error: cannot assign `string` to a `number`

そしてもちろんどんなネストでも:

let foo = {
    bar: [1, 3, 4]
};
// foo.bar[0] = 'hello'; // Would error: cannot assign `string` to a `number`

分解(Destructuring)

そしてもちろん、構造の分解でも機能します:

let foo = {
    a: 123,
    b: 456
};
let {a} = foo;
// a = "hello"; // Would Error: cannot assign `string` to a `number`

配列:

const bar = [1, 2];
let [a, b] = bar;
// a = "hello"; // Would Error: cannot assign `string` to a `number`

関数のパラメータの型が推測できれば、その構造化されたプロパティも同様に推測されます。例えばここでは引数をa/bのメンバに分解します。

type Adder = (numbers: { a: number, b: number }) => number;
function iTakeAnAdder(adder: Adder) {
    return adder({ a: 1, b: 2 });
}
iTakeAnAdder(({a, b}) => { // Types of `a` and `b` are inferred
    // a = "hello"; // Would Error: cannot assign `string` to a `number`
    return a + b;
})

Type Guard (Type Guards)

警告(Warnings)

パラメータに注意してください

代入から推論できない場合、型は関数パラメータに流れません。たとえば次のような場合、コンパイラはfooの型を知らないので、aやbの型を推論することはできません。

const foo = (a,b) => { /* do something */ };

しかし、 fooに型を指定された場合、関数パラメータの型を推論することができます(以下の例ではa、bは両方ともnumber型であると推測されます)。

type TwoNumberFunction = (a: number, b: number) => void;
const foo: TwoNumberFunction = (a, b) => { /* do something */ };

returnに注意してください

TypeScriptは一般的に関数の戻り値の型を推測することができますが、期待通りではない可能性があります。例えば、ここでは関数fooはanyの戻り値の型を持っています。

function foo(a: number, b: number) {
    return a + addOne(b);
}
// Some external function in a library someone wrote in JavaScript
function addOne(a) {
    return a + 1;
}

これは、addOneの型定義が悪いため、fooの戻り値の型が影響を受けたものです(aはanyなのでaddOneの戻り値はanyで、fooの戻り値はany)。

関数の返り値を明示するのが最も簡単だと分かります。結局のところ、これらのアノテーションは定理であり、関数本体が証明です。

想像できる他のケースもありますが、良いニュースは、そのようなバグを捕まえるのに役立つコンパイラフラグがあることです。

noImplicitAny

フラグ noImplicitAnyは、変数の型を推測できない場合(したがって、暗黙のany型としてしか持つことができない場合)、エラーを発生させるようにコンパイラに指示します。それによって、次のことが可能です。

  • そうしたい場合は、明示的に:any型の注釈を加えることでany型にしたい

  • 正しいアノテーションを追加することによってコンパイラを助ける

前へジェネリック型次へ型の互換性

最終更新 2 年前

役に立ちましたか?

が(特にユニオン型の場合に)どのように型を変更したり絞り込んだりするのかを見てきました。TypeGuardは、ブロック内の変数の型推論の別の形式です。

Type Guard