Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/playground example to ja #537

Merged
merged 3 commits into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//// { compiler: { }, order: 3 }

// TypeScriptのエラーメッセージはときどき、少しだけ冗長になってしまうことがあります。
// 3.7では、特にひどいいくつかの事例を
// 取り上げました。

// 入れ子のプロパティ

let a = { b: { c: { d: { e: "string" } } } };
let b = { b: { c: { d: { e: 12 } } } };

a = b;

// 以前は、入れ子のプロパティ1つにつき2行のコードでした。
// これは、エラーメッセージの最初と最後の行を読むことで、
// エラーメッセージの読み方をすぐに学べるということを意味していました。

// 今は、これらはインラインになりました。:tada:

// 3.6では以下のようになっていました:
//
// Type '{ b: { c: { d: { e: number; }; }; }; }' is not assignable to type '{ b: { c: { d: { e: string; }; }; }; }'.
// Types of property 'b' are incompatible.
// Type '{ c: { d: { e: number; }; }; }' is not assignable to type '{ c: { d: { e: string; }; }; }'.
// Types of property 'c' are incompatible.
// Type '{ d: { e: number; }; }' is not assignable to type '{ d: { e: string; }; }'.
// Types of property 'd' are incompatible.
// Type '{ e: number; }' is not assignable to type '{ e: string; }'.
// Types of property 'e' are incompatible.
// Type 'number' is not assignable to type 'string'

// これによって、様々な形のオブジェクトに対しても、
// 有用で簡潔なエラーメッセージを表示することができるようになりました。

class ExampleClass {
state = "ok";
}

class OtherClass {
state = 12;
}

let x = { a: { b: { c: { d: { e: { f: ExampleClass } } } } } };
let y = { a: { b: { c: { d: { e: { f: OtherClass } } } } } };
x = y;

// 3.6では以下のようになっていました:
//
// Type '{ a: { b: { c: { d: { e: { f: typeof OtherClass; }; }; }; }; }; }' is not assignable to type '{ a: { b: { c: { d: { e: { f: typeof ExampleClass; }; }; }; }; }; }'.
// Types of property 'a' are incompatible.
// Type '{ b: { c: { d: { e: { f: typeof OtherClass; }; }; }; }; }' is not assignable to type '{ b: { c: { d: { e: { f: typeof ExampleClass; }; }; }; }; }'.
// Types of property 'b' are incompatible.
// Type '{ c: { d: { e: { f: typeof OtherClass; }; }; }; }' is not assignable to type '{ c: { d: { e: { f: typeof ExampleClass; }; }; }; }'.
// Types of property 'c' are incompatible.
// Type '{ d: { e: { f: typeof OtherClass; }; }; }' is not assignable to type '{ d: { e: { f: typeof ExampleClass; }; }; }'.
// Types of property 'd' are incompatible.
// Type '{ e: { f: typeof OtherClass; }; }' is not assignable to type '{ e: { f: typeof ExampleClass; }; }'.
// Types of property 'e' are incompatible.
// Type '{ f: typeof OtherClass; }' is not assignable to type '{ f: typeof ExampleClass; }'.
// Types of property 'f' are incompatible.
// Type 'typeof OtherClass' is not assignable to type 'typeof ExampleClass'.
// Type 'OtherClass' is not assignable to type 'ExampleClass'.
// Types of property 'state' are incompatible.
// Type 'number' is not assignable to type 'string'
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//// { compiler: { }, order: 2 }

// Null合体演算子は左辺が
// nullまたはundefinedのときに
// 右辺の式を返す||演算子の代わりです。

// Null合体演算子とは対照的に、||演算子は空文字列や数字の0がfalseと判断される
// falsyチェックを用います。

// この機能の良い例は、
// キーが渡されなかったときに部分オブジェクトがデフォルト値を持つように処理する操作です。

interface AppConfiguration {
// デフォルト: "(no name)"; 空文字列は有効
name: string;

// デフォルト: -1; 0は有効
items: number;

// デフォルト: true
active: boolean;
}

function updateApp(config: Partial<AppConfiguration>) {
// Null合体演算子を使ったとき
config.name = config.name ?? "(no name)";
config.items = config.items ?? -1;
config.active = config.active ?? true;

// Null合体演算子を使わない現在の解決法
config.name = typeof config.name === "string" ? config.name : "(no name)";
config.items = typeof config.items === "number" ? config.items : -1;
config.active = typeof config.active === "boolean" ? config.active : true;

// ||演算子を用いると有効でないデータになる可能性がある
config.name = config.name || "(no name)"; // "" の入力が許容できない
config.items = config.items || -1; // 0の入力が許容できない
config.active = config.active || true; // とても悪いことに、常にtrueになる
}

// 3.7のリリース記事にて、Null合体演算子についてより詳細に知ることができます:
//
// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//// { compiler: { }, order: 1 }

// オプショナルチェイニングは3.7の開発中にTC39のStage 3合意に達しました。
// オプショナルチェイニングによって
// nullまたはundefinedだったときに
// 式の実行を即座に止めるコードが書けるようになります。

// プロパティへのアクセス

// データの中にアーティストそのものの情報やアーティストのプロフィールがない可能性がある
// アルバム情報を想像してみましょう。例えば、コンピレーションアルバムは
// 単一のアーティストについての情報を持っていないでしょう。

type AlbumAPIResponse = {
title: string;
artist?: {
name: string;
bio?: string;
previousAlbums?: string[];
};
};

declare const album: AlbumAPIResponse;

// オプショナルチェイニングを用いると、
// コードは以下のように書けます。

const artistBio = album?.artist?.bio;

// 以下のように書く代わりに:

const maybeArtistBio = album.artist && album.artist.bio;

// 演算子は"falsy"な値(例えば、空文字列や0、NaN、もちろんfalse)に
// 対して異なる振る舞いをするため、
// この場合、?.演算子は&&演算子とは異なる振る舞いをします。

// オプショナルチェイニングはnullまたはundefinedのみを
// 処理を止め、undefinedを返す合図と捉えます。

// オプショナルな要素へのアクセス

// プロパティへのアクセスは .演算子を用いて行われます。
// オプショナルチェイニングは要素にアクセス際の[]演算子でも同様に機能します。

const maybeArtistBioElement = album?.["artist"]?.["bio"];

const maybeFirstPreviousAlbum = album?.artist?.previousAlbums?.[0];

// オプショナルな呼び出し

// オプショナルチェイニングは、実行時に存在するか分からない関数を扱うときに、
// 関数が存在するときにだけ呼び出す機能をサポートしています。
// これによって、伝統的に書いていた次のような
// コードを置き換えられます: if (func) func()

// 以下はAPI requestからのcallbackに対する
// オプショナルな呼び出しの例です。

const callUpdateMetadata = (metadata: any) => Promise.resolve(metadata); // API呼び出しのダミー

const updateAlbumMetadata = async (metadata: any, callback?: () => void) => {
await callUpdateMetadata(metadata);

callback?.();
};

// 3.7のリリース記事にて、オプショナルチェイニングについてより詳細に知ることができます:
//
// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/