TypeScript x React

【よし!徹底的にやる!】TypeScriptのsubtype vs supertypeの違い

TypeScript x React
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

typescriptplayground

参考 プログラミングTypeScript


「武骨日記の」プライバシーポリシーに関して
プライバシーポリシー

サイトTOP
私は何者か
29歳よしもと芸人がWebデザイナー未経験で学校に通い5年後フリーランスのフロントエンドエンジニアになるためにやった9つのこと

フロント記事
フロントエンドエンジニア
フロントエンド記事(タグ)
TypeScript
TypeScript練習問題集(外部ページ)
GraphQL「Apollo x Relay-Style-Cursor-Pagination(リレースタイルカーソルページネーション)」
JavaScript練習問題
recomposeと仲良くなりたい
機動戦士FlowType
styled-componentsの使い方
初めてReactNativeWebを触ってみて
フロントエンドエンジニア豚汁の作り方
いちごタルトの作り方
SCSS問題集
Ramda.jsシグネチャの読み方
環境変数の話


「武骨日記の」プライバシーポリシーに関して
プライバシーポリシー

株式会社TerraceTechについて
最近起業しました。
株式会社TerraceTech

SNS
インド旅 instagram
適当な日常写真 instagram
シュールさーん instagram
シュールさーん LINEスタンプ
もりたけんじTwitter
ネタ帳Twitter
note

FaceBook -kennji.morita-

わたしが結成しているWebチームではWeb未経験者、フリーランスの方へのお仕事を紹介しています。
また個人レッスンしてほしい生徒も募集中です。
もしご興味ある方はチャットからご連絡ください。

※業務連絡やお久しぶり連絡もチャットからお願いします。