TypeScriptは、JavaScriptと特殊な関係にあります。TypeScriptはJavaScriptのすべての機能を提供し、さらにその上にTypeScriptの型システムという追加のレイヤーを提供します。
たとえば、JavaScriptはstring
やnumber
などの言語プリミティブを提供しますが、これらを一貫して割り当てたかどうかはチェックしません。TypeScriptはチェックします。
つまり、既存の動作するJavaScriptコードはTypeScriptコードでもあります。TypeScriptの主な利点は、コード内の予期しない動作を強調表示し、バグの可能性を減らすことができることです。
このチュートリアルでは、TypeScriptの概要を簡単に説明し、その型システムに焦点を当てます。
型推論による型
TypeScriptはJavaScript言語を理解しており、多くの場合、型を自動的に生成します。たとえば、変数を作成し、特定の値を代入すると、TypeScriptはその値を型として使用します。
tsTry
lethelloWorld = "Hello World";
JavaScriptの動作を理解することで、TypeScriptはJavaScriptコードを受け入れるが型を持つ型システムを構築できます。これにより、コードで型を明示的にするために追加の文字を追加する必要のない型システムが提供されます。上記例でhelloWorld
がstring
であるとTypeScriptが認識する方法です。
Visual Studio CodeでJavaScriptを記述したことがあり、エディターの自動補完を利用したことがあるかもしれません。Visual Studio Codeは、JavaScriptをより簡単に操作できるようにするために、内部でTypeScriptを使用しています。
型の定義
JavaScriptでは、さまざまなデザインパターンを使用できます。ただし、一部のデザインパターンでは、型を自動的に推論するのが難しい場合があります(たとえば、動的プログラミングを使用するパターン)。これらのケースをカバーするために、TypeScriptはJavaScript言語の拡張機能をサポートしており、型がどうあるべきかをTypeScriptに指示する場所を提供します。
たとえば、name: string
とid: number
を含む推論された型を持つオブジェクトを作成するには、次のように記述できます。
tsTry
constuser = {name : "Hayes",id : 0,};
interface
宣言を使用して、このオブジェクトの形状を明示的に記述できます。
tsTry
interfaceUser {name : string;id : number;}
その後、変数宣言の後に: TypeName
のような構文を使用して、JavaScriptオブジェクトが新しいinterface
の形状に準拠していることを宣言できます。
tsTry
constuser :User = {name : "Hayes",id : 0,};
提供したインターフェイスと一致しないオブジェクトを提供すると、TypeScriptが警告します。
tsTry
interfaceUser {name : string;id : number;}constuser :User = {Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.2322Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.username : "Hayes",id : 0,};
JavaScriptはクラスとオブジェクト指向プログラミングをサポートしているため、TypeScriptもサポートしています。クラスでインターフェイス宣言を使用できます。
tsTry
interfaceUser {name : string;id : number;}classUserAccount {name : string;id : number;constructor(name : string,id : number) {this.name =name ;this.id =id ;}}constuser :User = newUserAccount ("Murphy", 1);
インターフェイスを使用して、関数へのパラメーターと戻り値に注釈を付けることができます。
tsTry
functiondeleteUser (user :User ) {// ...}functiongetAdminUser ():User {//...}
JavaScriptには、すでにboolean
、bigint
、null
、number
、string
、symbol
、undefined
という小さなプリミティブ型のセットが用意されており、インターフェイスで使用できます。TypeScriptは、このリストをany
(すべてを許可)、unknown
(この型を使用する人が型を宣言することを保証)、never
(この型が発生する可能性はない)、およびvoid
(undefined
を返すか、戻り値がない関数)など、さらにいくつか追加して拡張します。
型を構築するための構文が2つあることがわかります:インターフェースと型。interface
を優先する必要があります。特定の機能が必要な場合はtype
を使用します。
型の構成
TypeScriptを使用すると、単純な型を組み合わせることで複雑な型を作成できます。これを行うには、ユニオンとジェネリックの2つの一般的な方法があります。
ユニオン型
ユニオン型を使うと、ある型が複数の型のいずれかであることを宣言できます。例えば、boolean
型を true
または false
のいずれかであると記述できます。
tsTry
typeMyBool = true | false;
注: 上記の MyBool
にマウスカーソルを合わせると、boolean
として分類されていることがわかります。これは構造型システムの特徴です。詳しくは後述します。
ユニオン型の一般的なユースケースは、値が許容される string
または number
の リテラルの集合を記述することです。
tsTry
typeWindowStates = "open" | "closed" | "minimized";typeLockStates = "locked" | "unlocked";typePositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
ユニオン型は、異なる型を扱う方法も提供します。例えば、array
または string
を受け取る関数があるかもしれません。
tsTry
functiongetLength (obj : string | string[]) {returnobj .length ;}
変数の型を調べるには、typeof
を使用します。
型 | 述語 |
---|---|
string | typeof s === "string" |
number | typeof n === "number" |
boolean | typeof b === "boolean" |
undefined | typeof undefined === "undefined" |
function | typeof f === "function" |
array | Array.isArray(a) |
例えば、文字列または配列のどちらが渡されたかによって異なる値を返す関数を作成できます。
tsTry
functionwrapInArray (obj : string | string[]) {if (typeofobj === "string") {return [obj ];}returnobj ;}
ジェネリクス
ジェネリクスは型に変数を提供します。一般的な例は配列です。ジェネリクスなしの配列には何でも含めることができます。ジェネリクス付きの配列は、配列に含まれる値を記述できます。
ts
type StringArray = Array<string>;type NumberArray = Array<number>;type ObjectWithNameArray = Array<{ name: string }>;
ジェネリクスを使用する独自の型を宣言できます。
tsTry
interfaceBackpack <Type > {add : (obj :Type ) => void;get : () =>Type ;}// This line is a shortcut to tell TypeScript there is a// constant called `backpack`, and to not worry about where it came from.declare constbackpack :Backpack <string>;// object is a string, because we declared it above as the variable part of Backpack.constobject =backpack .get ();// Since the backpack variable is a string, you can't pass a number to the add function.Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.backpack .add (23 );
構造型システム
TypeScript の中心的な原則の 1 つは、型チェックが値の持つ形状に焦点を当てていることです。これは「ダックタイピング」または「構造タイピング」と呼ばれることもあります。
構造型システムでは、2 つのオブジェクトが同じ形状を持つ場合、それらは同じ型であると見なされます。
tsTry
interfacePoint {x : number;y : number;}functionlogPoint (p :Point ) {console .log (`${p .x }, ${p .y }`);}// logs "12, 26"constpoint = {x : 12,y : 26 };logPoint (point );
point
変数は、Point
型であるとは宣言されていません。ただし、TypeScript は型チェック時に point
の形状と Point
の形状を比較します。それらは同じ形状であるため、コードは合格します。
形状の一致には、オブジェクトのフィールドのサブセットが一致しているだけで十分です。
tsTry
constpoint3 = {x : 12,y : 26,z : 89 };logPoint (point3 ); // logs "12, 26"constrect = {x : 33,y : 3,width : 30,height : 80 };logPoint (rect ); // logs "33, 3"constcolor = {hex : "#187ABF" };Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y2345Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, ylogPoint (); color
クラスとオブジェクトが形状に適合する方法に違いはありません。
tsTry
classVirtualPoint {x : number;y : number;constructor(x : number,y : number) {this.x =x ;this.y =y ;}}constnewVPoint = newVirtualPoint (13, 56);logPoint (newVPoint ); // logs "13, 56"
オブジェクトまたはクラスに必須プロパティがすべて含まれていれば、実装の詳細に関係なく、TypeScript はそれらが一致するとみなします。
次のステップ
これは、日常的な TypeScript で使用される構文とツールの簡単な概要でした。ここから、以下のことができます。
- 最初から最後までハンドブックをすべて読む
- Playground の例を調べる