fp-ts で実現可能なことを確認しました。
Literal.ts
export type Literal = StringLiteral | NumberLiteral;
export class StringLiteral {
constructor(readonly value: string) {}
}
export class NumberLiteral {
constructor(readonly value: string) {}
}
literals.ts
import * as Set from "fp-ts/Set";
import { type Eq } from "fp-ts/Eq";
import { type Literal, StringLiteral, NumberLiteral } from "./Literal";
const literalArray = [
new StringLiteral("42"),
new StringLiteral("42"),
new NumberLiteral("42"),
new NumberLiteral("42"),
];
const standardLiteralSet = new global.Set<Literal>(literalArray);
console.log("standard", standardLiteralSet);
const eqLiteral: Eq<Literal> = {
equals: (x, y) => {
return (
((x instanceof StringLiteral && y instanceof StringLiteral) ||
(x instanceof NumberLiteral && y instanceof NumberLiteral)) &&
x.value === y.value
);
},
};
const fpTsLiteralSet = Set.fromArray<Literal>(eqLiteral)(literalArray);
console.log("fp-ts", fpTsLiteralSet);
実行結果は以下の通りで、標準の Set では重複を排除できませんが、fp-ts の Set では比較に使う Eq を独自定義することで class と value の両方が一致するものは重複として排除されています。
standard Set(4) {
StringLiteral {
value: "42",
},
StringLiteral {
value: "42",
},
NumberLiteral {
value: "42",
},
NumberLiteral {
value: "42",
},
}
fp-ts Set(2) {
StringLiteral {
value: "42",
},
NumberLiteral {
value: "42",
},
}