なんのことかは、以下のコードがわかりやすいだろう、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