Typescript kontrollera om typ A === typ B | typ C
I en fil har jag något som detta:
export const _all = {
a: '',
b: '',
c: '',
d: '',
e: '',
f: '',
}
type AllKeysType = typeof _all;
export type AllKey = keyof AllKeysType;
I en annan fil har jag något sådant här:
export const _keep = {
a: '',
b: '',
d: '',
e: '',
}
type KeepKeysType = typeof _keep;
export type KeepKey = keyof KeepKeysType;
export const _ignore = {
c: '',
f: '',
}
type IgnoreKeysType = typeof _ignore;
export type IgnoreKey = keyof IgnoreKeysType;
Hur kan jag använda Typescript för att säkerställa att nycklarna definierade i _all ALLTID är lika med unionen av _keep och _ignore. Med andra ord bör AllKey alltid vara lika med KeepKey | IgnoreKey.
Jag vill att Typescript-kompilatorn ska ge mig ett fel om en utvecklare uppdaterar _all genom att lägga till ett nytt värde (till exempel z) men glömmer att lägga till z i antingen _keep eller _ignore.
Svar #1
Detta är möjligt genom att definiera en villkorlig typ som accepterar två typer och returnerar true när inmatningstyperna är lika eller false annars. Skriv sedan lite kod som kommer att orsaka ett kompileringsfel när den typen inte är true.
När någon av typerna ändras får du ett kompileringsfel vilket säkerställer att du kommer ihåg att uppdatera den typ som inte är synkroniserad. Detta är särskilt användbart när du vill bli meddelad om ändringar i en typ i ett annat bibliotek.
Till exempel:
type IsExact<T, U> = [T] extends [U] ? [U] extends [T] ? true : false : false;
function assert<T extends true | false>(expectTrue: T) {}
// this will throw a compile error when the two types get out of sync
assert<IsExact<AllKey, KeepKey | IgnoreKey>>(true);
Mer robust kod är lite längre (t.ex. hantering av any-typen), men den är hoprullad i mitt bibliotek här.
import { assert, IsExact } from "conditional-type-checks";
// define or import AllKey, KeepKey, IgnoreKey
assert<IsExact<AllKey, KeepKey | IgnoreKey>>(true);
Ett annat alternativ
Ett annat inte så trevligt sätt att göra detta på är att skapa två objekt av de två typerna och tilldela dem till varandra.
() => {
let allKeys: AllKey;
let otherKeys: KeepKey | IgnoreKey;
// do this in lambdas to prevent the first assignment from changing
// the type of the variable being assigned to
() => allKeys = otherKeys;
() => otherKeys = allKeys;
};
