Add support for $Diff

master
Paul Loyd 2017-12-02 16:03:29 +03:00
parent 72277118d5
commit 0408a93927
3 changed files with 74 additions and 1 deletions

View File

@ -135,6 +135,39 @@ function values(params: (?Type)[], resolve: TypeId => Type): ?Type {
return t.createUnion(variants);
}
function diff(params: (?Type)[], resolve: TypeId => Type): ?Type {
invariant(params.length === 2);
let [minuend, subtrahend] = params;
invariant(minuend && subtrahend);
invariant(minuend.kind === 'reference');
minuend = resolve(minuend.to);
invariant(minuend.kind === 'record');
if (subtrahend.kind === 'reference') {
subtrahend = resolve(subtrahend.to);
}
invariant(subtrahend.kind === 'record');
// TODO: more clever subtraction.
const blacklist = wu(subtrahend.fields).pluck('name').toArray();
const fields = wu(minuend.fields)
.filter(field => !blacklist.includes(field.name))
.map(field => ({
name: field.name,
value: t.clone(field.value),
required: field.required,
}))
.toArray();
return t.createRecord(fields);
}
export default {
Object: object,
Buffer: buffer,
@ -148,7 +181,7 @@ export default {
$Exact: unwrap, // TODO: another semantic for exact types?
$Keys: keys,
$Values: values,
// TODO: $Diff
$Diff: diff,
// TODO: $All
// TODO: $Either
};

View File

@ -0,0 +1,13 @@
type A = {
x: string,
y: boolean,
};
type B = {
y: boolean,
};
type X = $Diff<A, B>;
type Y = $Diff<A, {x: string}>;
export {X, Y};

View File

@ -0,0 +1,27 @@
- kind: record
fields:
- name: x
value: {kind: string}
required: true
- name: y
value: {kind: boolean}
required: true
id: [diffs, A]
- kind: record
fields:
- name: y
value: {kind: boolean}
required: true
id: [diffs, B]
- kind: record
fields:
- name: x
value: {kind: string}
required: true
id: [diffs, X]
- kind: record
fields:
- name: y
value: {kind: boolean}
required: true
id: [diffs, Y]