
TypeScript x React
【よし!徹底的にやるぞ!】TypeScriptのsubtypeとsupertypeの違い
背景
ちゃんと理解したいと思い勉強し直し。
普段何気なく使っている
let a: string = "hello"
は
aがstring
"hello"がstringリテラル
なので、リテラル型のスーパータイプであるstring型であるaはサブタイプである"hello"を代入できる
これをちゃんと説明できるように理解することにした
supertype(スーパータイプ)
スーパータイプとは
A >: B
となる関係。
・anyは全ての型のsupertypeである
・stringは"hello"のスーパータイプである。
・numberは1のスーパータイプである
・number | undefinedはnumberのスーパータイプである
・Animal型はPanda型のスーパータイプである
AはBのスーパータイプであるといえ、
スーパータイプAが要求するところはサブタイプBは代入できる
subtype(サブタイプ)
先ほどの逆
A <: B
となる関係、
・unknownは全ての型のsubtypeである。
・"hello"はstringのsubtypeである。
・1はnumberのsubtypeである
・numberのnumber | undefinedのsubtypeである
・Panda型はAnimalのsubtypeである
AはBのサブタイプであるといえ、
スーパータイプBが要求するところはサブタイプAは代入できる
let a = { name: "kenji" }
type A = typeof a
function afunc(o: A) {// 期待される型
return o
}
const b = { name: "morita", age: 100 } // プロパティの型
afunc(b)
// の時、期待される型は スーパータイプ
// 渡す型は サブタイプ
// B <: A (BはAのサブタイプか同じ型という意味)
// ということ
// Bは期待される型の「形状」を満たし、それぞれの型のサブタイプ or 同じ型なので代入できる。
///////////////////////////////////////////////////////////////
// 期待される型のスーパータイプであるプロパティの型をもつ形状は渡すことができない
type UnionA = number
type UnionB = string | number
type Obb = {
id?: number
}
const obb = {
id: "fafafa"
}
const obb2 = {
id: "fafa"
}
function bfunc(ob: Obb) {
return ob
}
bfunc(obb2)
////この意味は
// Argument of type '{ id: string; }' is not assignable to parameter of type 'Obb'.
// Types of property 'id' are incompatible.
// Type 'string' is not assignable to type 'number | undefined'.(2345)
// (サブタイプとなるべき)引数(bb2)は(スーパータイプの)Obbに割り当てられない
// idの型が間違っていて
// その型は、stringだが期待する型は number か undefined
// 共変
// オブジェクト、クラス、配列、関数の戻り値の型はそのメンバーに対して共変だが、
// 関数の変性(型の関係性)
//関数Aが関数Bのアリティ(パラメータ数)より少なく、且つ、次の条件を満たす場合は
// 関数Aは関数Bのサブタイプであり代入可能である
//1 Aのthis型が指定されていない、または「Aのthis型 >: Bのthis型」である。
//2. 対応するそれぞれのパラメータについて「Aのパラメータ型 >: Bのパラメータの型」である。(Aのパラメータの型はBのそれのスーパータイプである)
//3. 「Aの戻り値の型 <: Bの戻り値の型」である(共変)
type FA = (name: string) => string // サブタイプにしたい。(これを代入したい)
type FB = (name: string, age: number) => string
let fa: FA = (name: string) => { return name }
let fb: FB = (name: string, age: number) => { return name }
fb = fa // ok。上の条件を満たす。
// FAはFBのサブタイプ。FAはFBよりパラメータが少ない。且つ、this型は指定されていなく、条件3の型はの関係性は同じの型、戻り値も同じ型
// 実験1 引数が多い場合
type FA2 = (name: string, age: number, id: number) => string // 変更。 AはBより引数が多い
type FB2 = (name: string, age: number) => string
let fa2: FA2 = (name: string) => { return name } // 実際は違うけど、型アノテートされている。FAを消して推論させるとok
let fb2: FB2 = (name: string, age: number) => { return name }
fb2 = fa2 // error
// 実験2 戻り値を変えてみる
type ReturnFA3 = { name: string }
type ReturnFB3 = { name: string, age: number}
type FA3 = (name: string) => ReturnFA3 //
type FB3 = (name: string) => ReturnFB3
let fa3: FA3 = (name: string) => ({ name: "a" }) //
let fb3: FB3 = (name: string) => ({ name: "b", age: 10 }) // 上記条件3の { name: "b", age: 10 } は { name: "a" }のスーパータイプではければならない
fb3 = fa3 // error
// つまり、
type ReturnFA4 = { name: string, age: number, id: number }
type ReturnFB4 = { name: string, age: number}
type FA4 = (name: string) => ReturnFA4 // ReturnFA4はReturnFB4の全てのプロパティを持ち(とどうじに、余分なの1つあるし)、且つ、そのプロパティ型がsubtype
type FB4 = (name: string) => ReturnFB4
let fa4: FA4 = (name: string) => ({ name, age: 1, id: 12 }) // サブタイプとなった(共変)
let fb4: FB4 = (name: string) => ({ name, age: 10 })
fb4 = fa4 // error
「武骨日記の」プライバシーポリシーに関して
・プライバシーポリシー
・個人情報取り扱いに関して
・サイトTOP
・私は何者か
・29歳よしもと芸人がWebデザイナー未経験で学校に通い5年後フリーランスのフロントエンドエンジニアになるためにやった9つのこと
・フロント記事
・フロントエンドエンジニア
・フロントエンド記事(タグ)
・TypeScript
・TypeScript練習問題集
・【TypeScript】TypeSript中級者になる為に知っておくと良い108個のこと
・JavaScript練習問題
・styled-componentsの使い方
・SCSS問題集
・GraphQL「Apollo x Relay-Style-Cursor-Pagination(リレースタイルカーソルページネーション)」
・recomposeと仲良くなりたい
・機動戦士FlowType
・初めてReactNativeWebを触ってみて
・Ramda.jsシグネチャの読み方
・環境変数の話
・いちごタルトの作り方
・フロントエンドエンジニア豚汁の作り方
「武骨日記の」プライバシーポリシーに関して
プライバシーポリシー
株式会社TerraceTechについて
最近起業しました。
・株式会社TerraceTech
SNS
・しずかなインターネット kenjimorita
・インド旅 instagram
・適当な日常写真 instagram
・シュールさーん instagram
・シュールさーん LINEスタンプ
・もりたけんじTwitter
・ネタ帳Twitter
・note
※わたしが結成しているWebチームではWeb未経験者、フリーランスの方へのお仕事を紹介しています。
また個人レッスンしてほしい生徒も募集中です。
もしご興味ある方はチャットからご連絡ください。
※業務連絡やお久しぶり連絡もチャットからお願いします。