Kan jag tvinga det sista argumentet av en funktion i TypeScript?
Låt oss säga att jag har ett funktions-typgränssnitt som jag vill använda för att upprätthålla en viss signatur för specifika funktioner.
Finns det ett sätt att tvinga att det sista argumentet i en funktion måste vara en viss typ?
Finns det ett sätt att göra något liknande detta:
interface SomeType { /*...*/ }
/**
* this is the function type I want to enforce
* I want the last argument of any `Modifcation` to be `SomeType`
*/
interface Modification {
(...args: [...firstArgs: any[], lastArgument: SomeType]): void
}
// enforcing `Modification`
const someModification: Modification = (firstParam: string, second: number, third: SomeType) => {
/*...*/
}
Jag vet att TypeScript använder spridningssyntaxen och tuple-typer, men pseudokoden ovan fungerar inte.
Finns det ett sätt att göra detta?
Redigera:
Ansvarsfriskrivning: Jag tror inte att det finns ett sätt att göra det jag vill och den här frågan kanske därför inte är helt konstruktiv.
Kontext:
Jag har ett antal klasser och jag vill införa en viss konvention på specifika metoder i dessa klasser. Jag kan säkerställa att en viss metod måste följa en funktionstyp genom att deklarera ett annat gränssnitt och säga att min klass implementerar det gränssnittet.
t.ex.
interface Convention {(arg0: string, arg1: number): Something}
interface MyClassMethodRequirements {
myMethod: Convention,
myOtherMethod: Convention
}
class MyClass implements MyClassMethodRequirements {
myMethod(a: string, b: number) { return new Something(); }
myOtherMethod(label: string, aNumber: number) { return new Something(); }
otherMethod() { return 'just another non-conforming method' }
}
Vad jag vill uppnå:
Ovanstående Convention är bara ett exempel. Det jag vill upprätthålla är att en metod som påstås vara en Convention måste ha/ta hänsyn till båda parametrarna.
t.ex. (pseudo-kod)
interface NewConvention {(firstArg: any, lastArg?: RequiredType): Something}
interface MyClassMethodRequirements {
myMethod: NewConvention,
myOtherMethod: NewConvention
}
class MyClass implements MyClassMethodRequirements {
myMethod(a: string, b?: RequiredType) { return new Something(); }
// i want an error here because `myOtherMethod` doesn't list `lastArg: RequiredType` in it's parameters
myOtherMethod(label: string) { return new Something(); }
otherMethod() { return 'just another non-conforming method' }
}
För lite mer kontext, lastArg i NewConvention ska vara en valfri överskrivning.
Igen, jag tror inte att det jag försöker uppnå är möjligt, så detta kan vara okonstruktivt.
Tack för din hjälp :)
Svar #1
Om du känner till det maximala antalet parametrar kan du göra så många överlagringar som behövs.
type Modification =
{ (arg1: any, lastArgument: SomeType): void } |
{ (arg1: any, arg2: any, lastArgument: SomeType): void } |
{ (arg1: any, arg2: any, arg3: any, lastArgument: SomeType): void };
Svar #2
Du kan ha det första argumentet (av typen SomeType) som valfritt på följande sätt:
interface SomeType {
a: number; // just so it's not an empty definition
}
type Modification =
{ (first: SomeType, ...rest: (string | number)[]): void; }
| { (...rest: (string | number)[]): void; }
// fine
const someModification1: Modification = (firstParam: string, second: number) => {}
const someModification2: Modification = (third: SomeType, firstParam: string, second: number) => { }
// error
const someModification3: Modification = (firstParam: string, second: number, third: SomeType) => { }
Observera att om du använder any[] för argumenten så kommer det också att täcka SomeType-argumentet.
