
TypeScriptを用いたブラウザ上の画像処理【ライブラリ不使用】


TypeScript4.9からTypeScript4.6に遡って新機能をまとめています。4.5以前の内容は別記事にまとめています。まとめてある内容は文法レベルの新機能で、細かい改良及び仕様変更についてはまとめていません。ざっと新機能だけを確認するのが目的です。記事の後ろに行けば行くほど古いバージョンについて書いているため、知っているバージョンまでスクロールする必要はありません。各見出しの後には、公式ドキュメント(英語)に対応する項目を記載しております。
※この記事は逐次更新します。
こちらの記事でまとめております。
項目名:『The satisfies operator』
satisfied演算子というものが導入されました。
これを用いると、オブジェクトの『プロパティのスペルミスのチェック』と『プロパティの型推論』が同時にスマートに行われます。
以下のように、Color型をキーに、string | [number, number, number]型を値にもつオブジェクトpaletteを考えます。
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255]
// ~~~~ 1.blueと打ちたかったけどタイプミスした
// 型アノテーションしてないのでエラーは出ない
}
// 2. 以下の時点でredはnumber[]型と推論される
palette.red
型のアノテーションをしてないので、
①bleuとタイプミスしたプロパティにエラーは出ませんし、
②paltteは型推論により
{
red: number[];
green: string;
bleu: number[];
}
となるので、それぞれのプロパティ値が絞り込まれています。
①のプロパティのスペルミスをなくすために次のようにアノテーションをすると、今度は②の型推論でプロパティの型が絞り込まれなくなります。
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: "#00ff00",
blue: "hoge"
// bleu: [0, 0, 255]
// ~~~~ 1.blueというタイプミスは検出される
};
// 2. 以下はstring | RGBとなり型が絞り込まれない
// ので型推論が聞かない
palette.blue
型のアノテーションをしたので、
①bleuとタイプミスしたプロパティにエラー検出でき、
②paltteはstring | RGB型となる
よって、オブジェクトのプロパティにアクセスしても型が絞り込まれません。
これらの問題を解決するのが『satisfied演算子』です。
以下のように使います。
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
// ~~~~ 1.タイプミスは検出される
} satisfies Record<Colors, string | RGB>
//2.型の絞り込みも行われる
// [number, number, number]型になる
palette.red
オブジェクトのキーはsatisfiesで指定した型を最低限満たす必要があるので、
①Colors型にないキーはエラーとなります。
また、②型の絞り込みもスマートに行われています。
const foo = {
hoge: "hogehoge",
fuga: "fugafuga",
piyo: "piyopiyo",
// bar: 4 //エラー
} satisfies Record<string, string>
// 上のオブジェクトはRecord<string, string>を満たしたうえで次のような型になる
{
hoge: string
fuga: string,
piyo: string
}
項目名:『Auto-Accessors in Classes』
ECMAScriptの次期機能であるオートアクセッサーをサポートしています。クラスのプロパティに『accessor』をつけることで、次ようにクラスを省略して記述できます。
class Person {
accessor name: string;
constructor(name: string) {
this.name = name;
}
}
// このクラスは上クラスと同じ
class Person {
#__name: string;
get name() {
return this.#__name;
}
set name(value: string) {
this.#__name = name;
}
constructor(name: string) {
this.name = name;
}
}
項目名:『Checks For Equality on NaN』
以下の式はすべてエラーになります。NaNに対するチェックは、Number.isNaNを用いるようにします。
NaN === NaN
NaN !== NaN
NaN === 0
NaN !== 0
let someValue = 3
someValue === NaN
項目名: 『Improved Inference for infer Types in Template String Types』
テンプレート文字列型のinfer~extendsにおいて、リテラル型がきちんと推論されるようになりました。
なお、infer句をextendsと組み合わせる構文はTypeScript4.7で追加されています。
type Num<T> = T extends `${infer U extends number}` ? U : never;
type hoge = Num<'10'> //リテラルの10型。今まではnumber型。
項目名:『Errors When Comparing Object and Array Literals』
配列、オブジェクトのリテラルを比較するとエラーが出ます。
let hoge: number[] = []
if (hoge === []) {} //エラー
Javascriptでは配列やオブジェクトの比較は値ではなく参照が等しいかどうかを見ているので、値同士を比較していると勘違いした人によるバグを防止します。
項目名:『Control-Flow Analysis for Bracketed Element Access』
オブジェクトのキーがリテラル型かシンボルである場合、要素の型の絞り込みが可能となりました。
具体例を示します。
const key = Symbol();
const numberOrString = Math.random() < 0.5 ? 42 : "hello";
const obj = {
[key]: numberOrString,
};
if (typeof obj[key] === "string") {
// obj[key] はstring型に絞り込まれているのでtoUpperCase()が使える。
// 以前はstring | number型から絞り込めなかった
let str = obj[key].toUpperCase();
}
この改善によって、コンストラクタでプロパティが初期化されていないとエラーを吐くコードが書けます。
const key = Symbol();
class C {
[key]: string;
constructor(str: string) {
// [key]の初期化をしていないのでエラー
}
screamString() {
return this[key].toUpperCase();
}
}
項目名:『extends Constraints on infer Type Variables』
下記のように、infer句とextendsを組み合わせることで柔軟な型の記述が可能となりました。
type FirstIfString<T> =
T extends [infer S extends string, ...unknown[]]
? S
: never;
// string
type A = FirstIfString<[string, number, number]>;
// "hello"
type B = FirstIfString<["hello", number, number]>;
// "hello" | "world"
type C = FirstIfString<["hello" | "world", boolean]>;
// never
type D = FirstIfString<[boolean, number, string]>;
以下のコードは4.5以前だとエラーになっていました。
declare function doSomething(): void
class Hoge {}
class Fuga extends Hoge {
private piyo = 0
public constructor(){
doSomething() // 4.6より前だとエラー
super()
}
}
公式ドキュメント
https://www.typescriptlang.org/docs/handbook/release-notes/overview.html