型を見る会
Brand
型に { hoge: unknown }みたく何かしら(大体文字列)生やして独自に区別するような 悪用 活用ができる
いわゆる Phontom Type っぽいものらしい 👻
こういうのもある
code:foo.ts
// @see1 の記事のやつ
type Brand<K, T> = K & { __brand: T }
type USD = Brand<number, 'USD'>
type EUR = Brand<number, 'EUR'>
const usd = 10 as USD
const eur = 10 as EUR
function euroToUsd(euro: EUR): USD {
return (euro * 1.18 as USD)
}
console.log(USD: ${euroToUsd(eur)})
// -----------
// こっちのほうがまだ安全でいいですね
type Brand<T, U extends string> = T & { key in U: never } type Meat = 'Beaf' | 'Chicken'
type FoodPrice = Brand<number, Meat>
// うーん
const meat = (n: number) => n as FoodPrice
const logMeatPrice = (price: FoodPrice) => console.log(price)
logMeatPrice(meat(120)) // OK
logMeatPrice(120) // Error
ユーザー定義の型ガード
Brand と合わせると例えば File の拡張子判別とかが型レベルに出来る
code:foo.ts
type Wav = Brand<string, 'wav'>
type Mp3 = Brand<string, 'mp3'>
const wavRegexp = RegExp(/\.wav$/i)
const mp3Regexp = RegExp(/\.mp3$/i)
const isWav = (arg: string): arg is Wav => wavRegexp.test(arg)
const isMp3 = (arg: string): arg is Mp3 => mp3Regexp.test(arg)
const fileName = 'foo.wav' as Wav | Mp3 // ここ本当は upload されたやつ
if (isWav(fileName)) {
console.log(fileName) // Wav型
} else {
console.log(fileName) // Mp3型
}
as に近い存在なので乱用はやめといたほうがいいが、上のような場面はこうするしかなさそう
interface は instanceOf が使えないが、ユーザー定義の型ガードで型の確認が代用出来る
他にもメールアドレスのバリデーションを型レベルに出来る(普通にバリデーションやれって話かもしれないが)
code:validate-email.ts
export type Brand<T, U extends string> = T & { P in U: unknown } export type Email = Brand<string, 'email'>
if (isValidEmail(input)) console.log(input) // => Email型
Flow の $Diff
TypeScript だと Conditional Types で出来る
普通に Pick と Excludeで出来る
code:foo.ts
// これで T(union) から U を落とした union が取れる
// 一応 Diff
type Diff<T, U> = T extends U ? never : T;
type RequiredKeys = Diff<"foo" | "bar" | "piyo", "foo"> // "bar" | "piyo"
// Flow の $Diff
// オブジェクトの型突っ込んで Diff したのが取れる
// ----------
// Pick 使って書けるね
type $Diff<T, U> = Pick<T, Diff<keyof T, keyof U>>
type Props = { name: string, age: number }
type DefaultProps = { age: number }
type DiffedProps = $Diff<Props, DefaultProps> // { name: string } が取れる
// ----------
// Exclude でやれます
type $Diff<T, U> = Pick<T, Exclude<keyof T, keyof U>>
型でこういうの表現したいけどどうしよ〜ってときに見るもの
これ使って無理なら頭使う
タイピングしてぇ〜ってときに見るもの
寿司打に飽きたらどうぞ
中級ぐらいで気持ちがバキバキに折れた
PR 出すと採点までしてくれるらしい
お得〜!!おれはやりませんが...
TypeScript 型システム 健全性
TypeScript でイキリ始めた人間がいたらとりあえずこれ投げとけ感がある
全ての黒幕
↑の記事にもあるが、TypeScript の Array 型は 共変 しかし TypeScript の関数型の引数は 双変 扱いなのでコンパイルエラーにならないときがある 関数型の引数はふつう共変性はない
オッってなる
Promise の then の callback でこいつに噛まれたりする
元の記事見て〜
エンドユーザー殲滅作戦
TypeScript最終回