当サイトは、アフィリエイト広告を利用しています

【TypeScript】型アノテーションの使い方

作成日:2023月03月10日
更新日:2024年03月02日

TypeScriptの型定義方法として
TypeAnnotation(型アノテーション)があり

  • 変数
  • 関数
  • オブジェクト(連想配列)
  • Array(配列)

でそれぞれどう使うのかをサンプルを作りながらまとめる。

Type Annotation(型アノテーション)とは

型を宣言する時に「:」を使ってその右側に型を宣言することを

  • Type Annotation(型アノテーション)

と呼ぶ。
※型注釈と呼ぶ時もあります。

変数

型アノテーションで変数を宣言するサンプル

プリミティブ型

一番よく使う基本の型で
JavaScriptのプリミティブの型と対応している

変数(プリミティブ型)
//string
let moji:string = '文字列'
//数値
let kazu:number = 111
//boolean
let bool:boolean = true
  • 宣言した型以外の値を設定するとコンパイルエラーになる。

リテラル型

リテラル型には

  • 文字列のリテラル型
  • 数値のリテラル型
  • 真偽値のリテラル型

がある。
型アノテーションでリテラル型を使うと、そのプリミティブ型の特定の値のみしか
設定できなくなる。

変数(リテラル型)
//リテラル型_string
let retStr:"takeshi" = 'takeshi'//ok
retStr:"takeshi" = 'yoshio'//error
//リテラル型_number
let retNum:0 = 0//ok
retNum:0 = 1//error
//リテラル型_boolean
let retBool:false = false//ok
retBool:false = true//error

用途としてはユニオン型 (union type)と組み合わせて
ステータス管理などに使用される

ts
//ステータス管理
let status:'開始'|'処理中'|'終了' = '開始'
status = '処理中'
status = '終了'

関数

型アノテーションで関数を宣言するサンプル 関数の型定義では

  • 引数の型定義
  • 戻り値の型定義

をする。

基本構文

ちょっとわかりづらいので構文先に書くと
下記のようになる。

関数の型アノテーション構文
const func:(引数の型アノテーション)=>戻り値の型アノテーション = 関数
  • 「:」の右に引数の型アノテーションと戻り値の型アノテーションを先に書く。

関数の型アノテーションサンプル

実際の関数に当てはまめると下記のようになる。

関数の型アノテーション
//関数の型アノテーション
//戻り値なし
const func:(val:string)=> void = (foo)=>{
console.log(foo);
}
func("hoge")
// 実行結果
// hoge
//戻り値あり
const func2:(num1:number,num2:number)=>number = (num1,num2)=>{
return num1 + num2
}
console.log(func2(1,2));
// console.log(func2(1)); //error
// console.log(func2(1,'3')); //error
// 実行結果
// 3
//引数部分のみ型アノテーション
const func3 = (val:string)=>{
console.log(val);
}
func("hoge")
// 実行結果
// hoge
  • アノテーション指定した引数や戻り値の型や個数が違うとコンパイルエラーになる。
  • 引数部分のみに型アノテーションをつけることもできる。

オブジェクト(連想配列)

型アノテーションでオブジェクトを宣言するサンプル。
基本は下記の形になる

オブジェクトの型アノテーション
let obj: {
id: string,
name:string,
phoneNumber:number
} = {
id: '1',
name:'yoshio',
phoneNumber:111111
}
  • 「:」の次にオブジェクトの型アノテーションを宣言する

プロパティについて

基本は型アノテーションでオブジェクトを宣言した場合、
代入するオブジェクトは宣言したアノテーションの

  • プロパティをすべて持っている
  • プロパティの型が一致している

を満たしている必要があり、満たしていないとコンパイルエラーとなる。

関数の型アノテーション(エラー)
//コンパイルエラーとなる
let obj: {
id: string,
name:string,
phoneNumber:number
} = {
id: '1',
name:'yoshio',
}

例えば上記は型アノテーション宣言時に「phoneNumber」を
設定しているため、設定するオブジェクトに「phoneNumber」が
ないとコンパイルエラーとなる

とはいえそれだと、プロパティの省略や追加ができないので
したい場合は下記のようにする

プロパティを省略可能にする

プロパティの右側に「?」をつけることが
そのプロパティを省略可能にできる

プロパティ省略
let obj: {
id: string,
name:string,
phoneNumber?:number
} = {
id: '1',
name:'yoshio',
}
  • phoneNumberは省略可能となり、numberとundifinedを受け入れ可能になる。
プロパティを動的に設定できるようにする

インデックスシグネチャを使うことでプロパティ追加可能な型アノテーションを
宣言できる。

インデックスシグネチャ
let obj: { id:string
[key:string]: string;
} = {
id: '01',
name: 'masao'
};
console.log(JSON.stringify(obj,null,3));
// 実行結果
// {
// "id": "01",
// "name": "masao"
// }

インデックスシグネチャは

  • キーの型はstring型かnumber型のみ
  • インデックスシグネチャを含んだオブジェクトの全てのプロパティの型は同じにする
    ※?をつけるとundifinedも許容できるようになるためエラーとなる。

にする必要があり、満たさないとコンパイルエラーとなる

プロパティを読み取り専用にする

プロパティにreadonlyをつけることで
そのプロパティを読み取り専用にできる

readonly
let obj: {
readonly id:string
readonly [key:string]: string;
} = {
id: '1',
name: 'masao'
};
obj.id = '02'//error
obj.name = 'toshio'//error
  • readonlyが付いたプロパティは初期設定から変更できない
  • インデックスシグネチャにもreadonlyをつけることができる

配列

型アノテーションで配列を宣言するサンプル。
書き方は2種類があるがどっちでもいい。

配列の型アノテーション
let array1: number[];
array1 = [1, 2, 3];
//ジェネリクスを使う
let array2: Array<stirng>;
array2 = ['a', 'b', 'c'];

個人的にはジェネリクスのほうを書くことが多い気がします。

分割代入の型アノテーション

オブジェクトや配列を分割代入する場合も型アノテーションをつけることができる。
構文は下記のようになる。

分割代入構文(型アノテーション)
const {分割代入するプロパティ}:{型アノテーション} = 分割代入元オブジェクト

実装してみる

分割代入(型アノテーション実装)
//オブジェクト作成
const user:{
id: number;
name: string;
age: number;
}={
id:1,
name:'hoge',
age:21
}
//分割代入の型アノテーション
const {id,name}:{id:number,name:string} = user
console.log(id);
console.log(name);

注意点としてはオブジェクトで?をつけて省略可能にしてる
プロパティを分割代入しようとした場合、
分割代入の型アノテーションでも?をつけないとコンパイルエラーとなる

分割代入(型アノテーション実装)
//オブジェクト作成
const user:{
id: number;
name: string;
age?: number;
}={
id:1,
name:'hoge',
age:21
}
//分割代入の型アノテーション
// const {id,name,age}:{id:number,name:string,age:number} = user//error
const {id,name,age}:{id:number,name:string,age?:number} = user//ok
console.log(id);
console.log(name);
console.log(age);

コンポーネントのpropsで分割代入を使う

propsで分割代入を使う場合の型アノテーションは
下記のような感じ

App.tsx
/** @jsxImportSource @emotion/react */
import { StrStyle } from "./emotionCss";
//オブジェクト定義
type personalData = {
name: string;
age: string;
address: string;
};
//propsの定義
type propsType = {
data: personalData;
};
//分割代入する
const Person: (props: propsType) => JSX.Element = ({
data: { name, age, address }
}: propsType) => {
return (
<>
<h1>{name}</h1>
<h1>{age}</h1>
<h1>{address}</h1>
</>
);
};
export function App() {
let pdata: personalData = {
name: "takashi",
age: "11",
address: "tokyo"
};
return (
<div css={[StrStyle]}>
<Person data={pdata} />
</div>
);
}
  • 階層があるオブジェクトから分割代入している

typescript_props分割代入

TypeScriptの分割代入について下記記事でも紹介しています

まとめ

型アノテーションは宣言するもの(変数や関数、オブジェクト)によって
書き型が若干ちがったりして混乱するので、サンプルを作ってまとめてみた。
Typesciptを使っている時はいいのだが、使わなくなると多分、忘れてるので。。。

新着記事

タグ別一覧
top