TypeScript基本編
by Natsumi Chiba
文字列は’(シングルクォート)、”(ダブルクォート)、`(バッククォート)のいずれかで囲む
-
let direction: “north” “south” “east” “west”; -
let userName: string null = null; この は、またはという意味。
${name}さんは${age}歳です
- JavaScript と TypeScript共通の書き方
(Pythonはf”{ }) - 重要: ${ } は バッククォート(`)を使ったときにだけ有効
- “hello ${name}” 無効
hello ${name}有効
&& (論理 AND:ロジカル・アンド)とは?
JavaScript の 条件分岐に使う演算子
if (a && b) { … }
左が true のとき → 右も評価する
左が false のとき → 右を評価せず false(または左の値)を返す
&(Intersection型(交差型))とは?
A の特徴も持ち、B の特徴も持つ型
type C = A & B
TypeScript の ユニオン型(union type)は「A または B のどちらかの型を持てる」という型
記号 |(パイプ) を使います
interfaceとconstの違い
interface
型(Type)を定義する。データの“形”を決めるためだけに使う(型)
TypeScriptのみ
const
値(変数)を作る。実際のデータ(値)を作る
JavaScriptにもある
例1:API から取得したユーザー情報を扱う
// API から返ってくる データの形 を事前に定義しておく。
interface User {
id: number;
name: string;
email: string;
}
// JavaScript 実行時にも存在する「本物のオブジェクト」
const user: User = {
id: 1,
name: "Alice",
email: "alice@example.com"
};
例2:ログイン処理
// ログイン API に送るデータは必ず username と password が必要という ルールを決めるだけ。
interface LoginRequest {
username: string;
password: string;
}
// 実際にAPI に送るデータの実体。
const req: LoginRequest = {
username: "bob",
password: "secret123"
};
型ガードとは?
型ガード = 型を絞り込む if 条件
| ガード方法 | 型が絞り込まれる例 |
| ———————– | ———— |
| typeof x === "string" | x は string |
| typeof x === "number" | x は number |
| Array.isArray(x) | x は 配列 |
| x instanceof クラス名 | クラスのインスタンス |
| in 演算子 | プロパティを持つ型を判定 |
x is string | true のとき x を string に絞り込む
type と interface の違い
| 種類 | 何に使う? | 拡張のしやすさ | 向いている用途 | | ————- | —————————— | —————- | —————— | | interface | 主に「オブジェクトの形」を定義 | 拡張しやすい(再定義で追加可能) | APIレスポンス・クラスの型など | | type | なんでも作れる(オブジェクト・union・tuple など) | 再定義不可(上書きできない) | 複雑な型、ユニオン型、条件付き型など |
interface は「拡張しやすい」ので現場でかなり使われる
API 仕様が後から追加されるという例:
// 最初の定義
interface User {
id: number;
name: string;
}
→ あとで API に「email が追加されました」となったとする
// interface は「追加で拡張」できる
interface User {
email: string;
}
type は再定義できない(上書き禁止)ので、上記をTypeでやるとエラーになる
➡ type は1回しか定義できない
➡ 拡張が必要な場面では interface が向いている
type は万能型 → union や tuple などに使う
こういうのは interface ではできない(or 書きづらい)
// union 型を作る
type ApiResult = “success” | “error”;
// tuple を作る
type GeoPoint = [number, number];
// 関数の型 alias を作る
type Callback = (msg: string) => void;
interface も type も「オブジェクト型」を作れる(共通部分)
type Product = { id: number; name: string; };
interface Product { id: number; name: string; }
使い分け例
- API のレスポンス → interface
API 仕様が後で変更されやすい → 拡張性が必要 - ボタンの状態 → type(ユニオン型)
union 型は type で書く方が自然で簡潔 - 関数の型 → type
type は関数型との相性が良い - クラスに適用する型 → interface
クラスの implements に使うときは interface が向いている
| 目的 | 使うべき |
|---|---|
| オブジェクトの設計図を定義したい | interface |
| オブジェクトを後から拡張したい | interface |
| union/tuple/関数型など複雑な型 | type |
| 開発チームで広く共有する型 | interface(拡張しやすい) |
| カッチリ固定した型 | type |
<T> や <U> は、TypeScript の ジェネリクス(Generics) という仕組み
T や U は 具体的な型の名前ではなく、あとから自由に差し込める “型の変数”
T は「この関数が受け取る値の型」
U は「この関数が返す値の型」
どちらも 実際に関数を使うときに決まる
any型には、文字列、数値、配列、オブジェクト等を自由に代入可能です
any型は、プログラムを作る途中で型チェックを一時的に避けたいときにも使われる
タプル型(Tuple type)
順番と型の両方が決まっている配列のこと
// 普通の配列
number[] // 数がいくつあってもOK、全部 number
string[] // いくつでもOK、全部 string
//タプル型
let person: [string, number];
interface型の利用
object型はあまり使われず、interfaceを使用することが推奨されています
interfaceでは、型の再利用性やコードの可読性が向上します。また、型の定義が簡単になります
「オブジェクトの形(型)」を定義するもの
interface User {
name: string
}
implements
「このクラスは、この interface の形を必ず守ります」と約束するもの
implements の役割は「チェック」だけ
完全に「コンパイル時のルール確認用」
array型は配列を値として取る型
型の定義方法としては型名[]とArray<型名>があり、どちらを使用しても問題ありません。型名>
mapped type
「既存の型をもとに、新しい型を“自動生成する仕組み”」。
TypeScript が提供する 型の for 文(ループ) のようなもの。
型をループして新しい型を作る仕組み
keyof
オブジェクトのキー一覧を union 型で返す
union 型(ユニオン型)
「A または B のどちらかになる型」→だからletを使う |(パイプ)を使って書く let 変数名 = 型1 | 型2 | 型3 | … ;
numOrString
この変数は、number型またはstring型の値を持つことができます。
let numOrString: number | string;
numOrString= 42;
numOrString= "こんにちは";
複数の型は配列にも利用できます。下記は、文字列と数値を格納できる配列を定義する例
// Unionを使った配列の型注釈
const array: (string | number)[] = ['Apple', 10, 'Orange', 'Banana', 20]
“hello”.toUpperCase();
toUpperCase() は、文字列(string)を“全部大文字に変換する”メソッド
toLowerCase()(小文字にするメソッド)もあり
?(optional property)
?はプロパティが存在しない場合でもエラーが発生せず、安全にアクセスすることができる
interface Person {
name: string
age?: number
}
const greet = (person: Person) => {
console.log(`Hello, ${person.name}!`)
if (person.age) {
console.log(`You are ${person.age} years old.`)
}
}
greet({ name: 'Alice', age: 25 })
// 'Hello, Alice!'
// 'You are 25 years old.'
greet({ name: 'Bob' })
// 'Hello, Bob!'
?(optional chaining)
undefinedかnullの可能性があるプロパティにアクセスしようとした際に、エラーを防ぐことができる。
const sampleFunction = (user: any) => {
console.log(user.name?.value)
}
sampleFunction({ age: 20 })
// undefined
-? (オプショナル修飾子)を外す
[K in keyof T]-?: T[K]
元が foo?: string でも
-? をつけることで foo: string に戻せます。
!== は「型も値も厳密に比較して、等しくないときに true になる
// 「data が undefined ではないときだけ実行する」
if (data !== undefined)
! は Non-null assertion operator(非 null アサーション) と呼ばれます
x! = 「x は null でも undefined でもないと“断言”する」
// 記号は同じでも、位置が違うと意味がぜんぜん違う
!x → JavaScript の論理否定(not x)
x! → TypeScript の非 null アサーション(x は null / undefined ではない」とコンパイラに言い張る(TS固有))
unknown
値が不明な場合に使用します。具体的な型を指定せず、実行時に値の型をチェックする必要がある場合に使用されます
let something: unknown = 10
something = 'Hello'
something = true
typeof
指定された値の型を取得するために使用されます
console.log(typeof 100) // ‘number’
console.log(typeof ‘Hello World’) // ‘string’
console.log(typeof true) // ‘boolean’
型アサーション(asもしくは<>)
変数に対して型を明示的に指定して、コンパイラに対してその変数の型を教えることができる機能です。
2つの方法があり、asキーワードと<>を使って表現することができます。
// asを使った型アサーションの書き方
const name: string | undefined = 'John'
const nameLength: number = (name as string).length
// <>を使った型アサーションの書き方
const name: string | undefined = 'John'
const nameLength: number = (<string>name).length
リテラル型
- 特定の値そのものだけを許可する型
- 「値」=「型」になる 通常は string や number が型ですが、リテラル型では “hello” や 42 など 値そのもの が型になります。
- 文字列リテラル型・数値リテラル型・真偽値リテラル型がある
-
type Direction = "left" | "right"; type StatusCode = 200 | 404 | 500; type Flag = true | false;
as const
プロパティが readonly になる(浅い readonly)
文字列・数値などがリテラル型に固定される
配列は読み取り専用タプルになる
toString()
JavaScript(TypeScript)で使われる、文字列(string)に変換する方法
number と string の共通処理として使える
| 値 | toString() の結果 |
| ——- | ——————– |
| number | "123" のように文字になる |
| string | そのまま |
| boolean | "true" / "false" |
| array | "1,2,3" のように並ぶ |
| object | "[object Object]" |
##
tags: