4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeScript まとめ1(型について)

Last updated at Posted at 2021-04-09

TypeScriptまとめ集

  1. 型について
  2. ユーティリティ型
  3. モジュール化
  4. インストール〜コンパイル方法

目次

  1. TypeScriptとは?
  2. 型について
  3. 関数
  4. 高度な型について
  5. インターフェイスを使用した型定義

1.TypeScriptとは?

  • altJS(JavaScriptの代替言語)の一種。
  • altJSは他にもCoffeScript, Dart, Elm, ClojureScriptなどが存在する。
  • TypeScriptはJavaScriptにはできなかった変数、関数の型宣言が可能。
  • Angular, React, Vue.jsなどのJavaScriptフレームワークで標準採用されている。

2.型について

型の種類

基本となるプリミティブ型

説明
number 数値型(整数/浮動小数点数) 1, -1, 0.5
string 文字列型 'aiueo', "あいうえお"
boolean 真偽型(true/false) true, false
symbol シンボル型 Symbol('あいうえお')
null null null
undefined undefined undefined

プリミティブ型以外の型

説明
any 任意の型 1, 'あいうえお', true
unknown 型が不明 1, 'あいうえお', true
array 配列型 [1, 2, 3]
tuple タプル型(配列型の中でも値の型が統一されていないもの) [1, 'AAA', true]
enum 列挙型 省略(後述の例文で紹介)
function 関数 省略(後述の例文で紹介)
void 戻り値なし 省略(後述の例文で紹介)
never 絶対に起こらない 無限ループ、常にエラーを吐き出すなど
それ以外 Date, RegExp, JSON, URLなど 色々
  • 型を省略した場合はany型扱いになる。
  • any型とunknown型は似ているが、any型は各型のプロパティが使用できるのに対し、unknown型は使用できない。
  • サイトによってプリミティブ型の定義が違っていたりするため、注意(これもあっているか微妙)。
typescript(プリミティブ型の型宣言)
//数値型
let num:number = 100;

//文字列型
let str:string = 'qiita';

//真偽型
let bool:boolean = true;

//シンボル型
let sym:symbol = Symbol('qiita'); 

//null
let nul:null = null;

//undefined
let und:undefined = undefined;
typescript(プリミティブ型以外の型宣言)

//any型(何でも代入できる、ただし基本は使わないこと)
let any1:any = 1;
any1.indexOf(1);  //コンパイルは通るが、実行時エラー

//unknown型
let unknown1:unknown = 1;
unknown1.indexOf(1);  //コンパイルエラー

//配列型
let array1:string[] = ['C#', 'Java', 'Ruby', 'Python'];
let array2:number[][] = [[10,20],[30,40],[50,60]];
let array3:Array<string> = ['C#', 'Java', 'Ruby', 'Python'];
let array4:Array<[number,number]> = [[10,20],[30,40],[50,60]];

//読み取り専用の配列
//ただし、readonlyキーワードがチェックするのは一次元目の要素のみ
let array5: readonly string[] = ['Java','Python','PHP','Ruby'];
let array6: ReadonlyArray<string> = ['Java','Python','PHP','Ruby'];
array3[1] = 'Python 3';    //結果:エラー

//連想配列
let dict1: { [index: string]: string } = {
  'hoge': 'ほげ',
  'foo': 'ふぅ',
  'bar': 'ばぁ',
};

//タプル型 複数の異なる型の集合を表すためのデータ型
let tuple1: [string,number,boolean] = ['hoge',10.355,false];

//列挙型
//値を割り当てない場合は、上から0,1,2と値が振り分けられる
enum enum1{
  MALE = 0,
  FEMALE = 2,
  OTHER = 4
}
let m:enum1 = enum1.OTHER;
console.log(m);         //結果:4
console.log(enum1[m]);  //結果:OTHER

//関数
function func1(arg1:string, arg2?:number=0){
  return `${arg1}の値は${arg2}です。`
}

//void型
function void func2(arg1:string, arg2:number=0){
  console.log('戻り値なし');
}

//never型
function func3(message: string): never {
    throw new Error(message);
}

//それ以外
let date:Date = new Date();

型変換

  • 型変換をしたい場合は、以下の2種類のやり方で変換できる
typescript(型変換)
let str:string = '100';

//<型名> で変換する
let num1:number = <number>str;

//as 型名 で変換する
let num2:number = str as number;

3.関数

関数の宣言方法

関数の宣言方法は

  • function
  • 関数リテラル
  • アロー関数(ラムダ式)
    の3種類がある。
typescript(関数の宣言方法)
//function
function triangle(base: number, height: number):number{
  return base * height / 2;
}

//関数リテラル(2パターン)
let triangle = function(base: number, height: number): number {
  return base * height / 2;
}
let triangle: (base: number, height: number) => number =
  function (base: number, height: number): number {
    return base * height / 2;
}

//アロー関数(ラムダ式)(2パターン)
let triangle = (base: number, height: number):number => {
  return base * height / 2;
};
let triangle = (base: number, height: number):number => base * height / 2;

戻り値、引数について

  • void, neverの使用方法について
  • 引数を省略、既定値、可変調などの設定方法について
typescript(色々な関数)

//void 戻り値なし
function VoidFunc(name: string): void{
  console.log(`こんにちは、${name}さん!`);
}

//never 決してありえない(常に例外を出す、無限ループとなっているなど、終点に到達できない)
function NeverFunc(): never {
  throw new Error('Error is occured.');
}

//引数を省略可能
function OmitFunc(name?:string):string{
  if(val === undefined){
    return `こんにちは、名無しさん!`;
  } else {
    return `こんにちは、${name}`さん!;
  }
}

//引数の既定値
function DefaultFunc(name:string='佐藤'):string{
  return `こんにちは、${name}さん!`;
}

//可変調引数
function VariableFunc(...values: number[]){
  let result = 0;
  for(let value of values){
    result += value;
  }
  return result;
}

オーバーロード

  • オーバーロード...同じ名前でありながら、引数・戻り値の型が異なる関数を定義すること
typescript(オーバーロード)

//シグニチャだけの関数を準備
function show(value: number):void;
function show(value: boolean):void;

//オーバーロードした全ての型に対して有効となるように実装する
function show(value: any): void{
  if(typeof value === 'number') {
    ...
  } else {
    ...
  }
}

4.高度な型について

共用型

「複数の値の中のどれか」を表す型

typescript(共用型)
//変数
let data: string | boolean;
data = 'hoge';
data = false;

//関数(戻り値)
function square(value: number): number | boolean {
  if(value < 0){
    return false;
  } else {
    return number + 1;
  }
}

//関数(引数)
function show(value: string | number): void {
  if(typeof value == 'string'){
    console.log('string型です。');
  } else {
    console.log('number型です。');
  }
}

型チェック

  • typeofは、プリミティブ型の判定のみに有効
  • instanceofはプリミティブ型以外の判定に有効
  • inは、特定のメンバーが存在するかを判定
typescript(型チェック)
//typeof演算子
function show(value: string | number): void {
  if(typeof value == 'string'){
    console.log('string型です。');
  } else {
    console.log('number型です。');
  }
}

//instanceof/in演算子
function show(value:Person):void{

  //instanceof演算子を使う場合
  if(value instanceof Person) { ... }

  //in演算子を使う場合
  //valueがnameプロパティを持つか
  if('name' in value) { ... }
}

ユーザー定義の型チェック

  • is演算子を使用することでユーザー定義の型チェック関数を自作できる
typescript(is演算子)
//戻り値がtrueであれば、引数がstring型であることを示している
function isString(test: any): test is string{
    return typeof test === "string";
}

//isStringを使っての関数
function example(foo: any){
    if(isString(foo)){
        //fooはstringであることがis演算子よりわかる
        //そのためlength(string型のメンバー)に安全にアクセスできる
        console.log(foo.length);  
    }
}

null非許容型

TypeScriptでは、既定で全ての型に対してnull/undefinedを設定可能だが、
tsconfig.json内のstrictNullChecksオプションにtrueを設定することで、
全ての型でnull/undefinedの設定を禁止できる。

typescript(null非許容型)
let data1:string = null;       //エラー
let data2:string = undefined;  //エラー

//null/undefinedを設定できるようにしたい場合には...
let data1;string|null = null;            //OK
let data2;string|undefined = undefined;  //OK

?.演算子

  • TypeScript3.7以降で使用可能に。
  • 「?.」演算子は、null/undefinedでない時にアクセス可能。
typescript(?.演算子)
//通常の場合
let hoge:string | null | undefined;
let result = (hoge === null || hoge === undefined) ? undefined : hoge.trim();

//?.の場合
//null,undefinedでなければ、trimを行う
let result = hoge?.trim();

//連続でも指定可能
hoge?.foo?.bar();

「??」演算子

  • TypeScript3.7以降で使用可能に。
  • 「??」演算子は、null/undefinedである時に既定値を返す。
typescript(??演算子)
//通常の場合
console.log((hoge !== null && hoge !== undefined) ? hoge : '×');

//??演算子の場合
//null,undefinedの場合に既定値を設定する
console.log(hoge ?? '×');

型エイリアス

特定の型に対して別名(エイリアス)を設定する。

typescript(型エイリアス)
//タプル型にFooTypeという名前を付与
type FooType = [string, number, boolean];

//FooType型の変数dataを定義
let data:FooType = ['abc',100,true];

文字列リテラル型

特定の文字列(文字列リテラル)をそのまま型として利用できる。

typescript(文字列リテラル型)
//Season型を定義
type Season = 'spring'|'summer'|'autumn'|'winter';

//Season型ならコンパイルOK
//Season型以外ならコンパイルエラー となる
function getScene(s:Season){...}
getScene('spring'); //OK
getScene('fall');   //エラー

ジェネリック型

汎用的なクラス/メソッドに対して、特定の型を紐づけるための機能

typescript(ジェネリック型)

//ジェネリックを定義
//Tには任意の型を入れることができる
class MyGenerics<T>{
  value!:T;
  getValue():T{
    return this.value;
  }
}

let g = new MyGenerics<string>();
g.value = 'Hoge';
console.log(g.getValue());  //結果:Hoge

ちなみに

typescript(ジェネリック型)
//複数型引数を指定できる
class MyGenerics<T,R>{...}
//型引数の既定値を設定
class MyGenerics<T=string>{...}
//型引数の制限を設定
class MyGenerics<T extends Hoge>{...}

クラスだけでなくメソッドにもつけることが可能

typescript(ジェネリック型)
//ジェネリックメソッド
class MyCollection{
  static addAll<T>(data:T[],...values:T[]):T[]{
    return data.concat(values);
  }
}

5.インターフェイスを使用した型定義

インターフェイスについては、モジュール化(未作成)を参考。

基本

typescript(インターフェイスによる型定義)
//インターフェイスで型を定義
interface Sample{
  name:string;     //プロパティシグニチャ
  hello():string;  //メソッドシグニチャ
}

//インターフェイスで定義した型の変数
let s:Sample{
  name:'Taro',
  hello(){
    return `こんにちは、Qiitaさん!`;
  }
}

※インターフェイスを定義せずに型情報を明示したい場合は、以下のようにできる(オブジェクト型リテラル)

typescript(オブジェクト型リテラル)
let s:{
  name:string,
  age:number
} = {
  name:'Taro',
  age:20
}

プロパティシグニチャ

  • 「?」で省略可能なプロパティを表せる
  • 「readonly」で読み取り専用プロパティを表せる
typescript(プロパティシグニチャ)
interface Sample{
  readonly name:string;
  age?:number;
}

コールシグニチャ

  • 関数型を宣言するためのシグニチャ。
  • 「(引数:型, ...):戻り値」の形式で宣言する。
typescript(コールシグニチャ)
interface hello {
  (name:string):string
}

let h:hello = function(name:string):string{
  return `こんにちは、Qiitaさん!`;
}

メソッドシグニチャ

  • メソッドの型を宣言するためのシグニチャ。
  • 「メソッド名(引数:型, ...):戻り値」の形式で宣言する。
typescript(メソッドシグニチャ)
interface Sample {
  hello(name:string):string
}

let h:Sample = {
  hello(name:string):string{
  return `こんにちは、Qiitaさん!`;
  }
}

インデックスシグニチャ

  • 連想配列で使用すると便利
typescript(インデックスシグニチャ)
interface NumberAssoc{
  [index:string]:Number
}

let list:NumberAssoc = {
  'hundred': 100,
  'thousand': 1000
};

コンストラクターシグニチャ

  • コンストラクターの型を宣言できる。
  • 「new(引数1, ...):クラス名」で定義できる。
typescript(コンストラクターシグニチャ)
//インターフェイス
interface Figure{
  new(width:number, height:number):Triangle;
}

//継承先
class Triangle{
  constructor(private width:number,private height:number){}
}

WeakType

  • すべてのプロパティが省略可能(~?)である型のこと
  • 全て省略した場合、もしくは全て入力した場合のみコンパイルが通るので注意。
typescript(WeakType)
//インターフェイス
interface MyOption{
  name?:string;
  timeout?:number;
}

let obj1:MyOptions = { name:'AAA'}; //エラー
let obj2:MyOptions = { }; //OK 
let obj3:MyOptions = { name:'AAA', timeout:10}; //OK

keyof

既存の型から、型情報を切り出すことができる。

typescript()
interface Product{
  name:string;
  price:number;
}

type ProductKeys = keyof Product;
//これと同義
type ProductKeys = "name"|"price";

LookupTypes

指定の型から配下のプロパティ型を抜き出すことができる。

typescript(LookupTypes)
interface Product{
  name:string;
  price:number;
}

//Product型配下のプロパティ型を取得
type NameType = Product['name'];  //string
type NamePriceType = Product['name'|'price'];  //string|number
type HogeType = Product['hoge']; //エラー

Mapped Types

  • 既存の型を変換するための仕組み。
  • ユーティリティ型も似た仕組み(TODO:URL)
typescript(MappedTypes)
interface Product{
  name:string;
  price:number;
}

//Product型のプロパティセットから順にプロパティ名を取り出し、Kに割り当てなさいという意味
//[K in keyof Product]が該当箇所
type ReadonlyProduct = {
  readonly [K in keyof Product]:Product[K]
;}

//これと同義
type ReadonlyProduct = {
  readonly name:string,
  readonly age:number
};

※ちなみに

  • 「-?」で「?」を解除できる
  • 「-readonly」で「readonly」を解除できる
typescript(MappedTypes)
interface ReadonlyProduct{
  readonly name:string;
  readonly price:number;
}

type Product = {
  -readonly [K in keyof Product]:ReadonlyProduct[K]
;}

//これと同義
type Product = {
  name:string,
  age:number
};

ConditionalTypes(条件型)

与えられた条件を満たすかどうかによってX,Yのいずれかの型を選択する
三項演算子と似たような感じ。

typescript(ConditionalTypes)

//型Tが型Uに代入できなければnever型を返す
type Intersection<T, U> = T extends U ? T:never;
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?