restricted polymorphism(@TypeScript)

なんのことかは、以下のコードがわかりやすいだろう、o’reillyからほぼそのままですが、


// restricted polymorphism
type TreeNode = {
    value: string
}

type LeafNode = TreeNode & {
    isLeaf: true
}

type InnerNode = TreeNode & {
    children: [TreeNode] | [TreeNode, TreeNode]
}

let a: TreeNode = {value: 'a'}
let b: LeafNode = {value: 'b', isLeaf: true}
let c: InnerNode = {value: 'c', children: [b]}

let a1 = mapNode(a, _ => _.toUpperCase())
let b1 = mapNode(b, _ => _.toUpperCase())
let c1 = mapNode(c, _ => _.toUpperCase())

function mapNode<T extends TreeNode>(       // if omit extends, node.value makes error since TypeScript
    node: T,                                // cann't define type of the value
    f: (value: string) => String
    ): T{
        return {
            ...node,
            value: f(node.value)
        }
    }

console.log(a, a1)      // { value: 'a' } { value: 'A' }
console.log(b, b1)      // { value: 'b', isLeaf: true } { value: 'B', isLeaf: true }
console.log(c, c1)      // { value: 'c', children: [ { value: 'b', isLeaf: true } ] } { value: 'C', children: [ { value: 'b', isLeaf: true } ] }

TreeNode以下をtype定義しているので、それを継承したTはnode.valueにアクセス可能、TreeNodeを継承しないでTだけならばnode.valueはTypeScriptが型を決められないのでエラーになります。

制約(この場合にはTreeNode)が複数必要な場合にはそれらを&で連結すれば良い。

 

admin