javascript - Argumente condiționale
Aș dori să creez o funcție care să restricționeze argumentele transmise. dpr și w nu ar trebui să fie transmise ambele în același timp. Iată încercarea mea:
Teren de joacă
interface W { w: number }
interface Dpr { dpr: number }
type Srcset<T> = { url: string } & WidthOrDpr<T>
type WidthOrDpr<T> = T extends W ? W : Dpr;
function formatSrcset<T extends W | Dpr>(options: Srcset<T>) {
}
formatSrcset({ url: '//', dpr: 1 }); // ok
formatSrcset({ url: '//', w: 1 }); // ok
formatSrcset({ url: '//', w: 1, dpr: 1 }); // should fail
Aș dori să evit suprasarcina funcțiilor.
Răspuns #1
Acesta nu este cel mai concis cod, dar ce-ar fi dacă ai forța ca dpr/w să fie nedefinite prin definirea a două interfețe pentru diferitele opțiuni de argumente? Ceva de genul acesta:
type Args1 = { dpr: number, w?: undefined };
type Args2 = { dpr?: undefined, w: number };
type Srcset<T> = { url: string } & (Args1 | Args2);
Răspunsul #2
Poți folosi type-fest's RequireAtLeastOne
// code from sindresorhus/type-fest
type RequireAtLeastOne<
ObjectType,
KeysType extends keyof ObjectType = keyof ObjectType,
> = {
// For each `Key` in `KeysType` make a mapped type:
[Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required
// 2. Make all other keys in `KeysType` optional
Partial<Pick<ObjectType, Exclude<KeysType, Key>>>;
}[KeysType] &
// 3. Add the remaining keys not in `KeysType`
Except<ObjectType, KeysType>;
În cazul tău
type Args = RequireAtLeastOne<{
url: string
dpr?: number
w?: number
}, 'dpr' | 'w'>
function fn({ url, dpr, w }: Args) {...}
