TypeScript's type checker has a blind spot: if you implement an interface with fewer
parameters than declared, it compiles silently. I added a check that rejects it.
The problem:
interface Door {
open(key: string, code: number): void
}
class MyDoor implements Door {
open(key: string) { }
// compiles in TypeScript, no error
}
The reasoning in TypeScript is that functions are free to ignore extra arguments —
that's intentional for callbacks like array.map((value, index) => ...) where you
often omit index. But for interface/class method implementations, this isn't a
callback pattern — it's a contract. If the interface says open takes two arguments,
a class claiming to implement it should match that arity.
The fix is 22 lines added to internal/checker/relater.go in microsoft/typescript-go:
var sourceHasFewerParameters bool
// Only check for fewer parameters when comparing interface/class method
// implementations, not for function assignments or callback functions.
if checkMode&SignatureCheckModeCallback == 0 &&
(kind == ast.KindMethodDeclaration ||
kind == ast.KindMethodSignature ||
kind == ast.KindConstructor ||
kind == ast.KindConstructSignature) {
if !c.hasEffectiveRestParameter(source) {
if checkMode&SignatureCheckModeStrictArity != 0 {
sourceHasFewerParameters = c.hasEffectiveRestParameter(target) ||
sourceCount < targetCount
} else {
sourceHasFewerParameters = sourceCount <
c.getMinArgumentCount(target)
}
}
}
if sourceHasFewerParameters {
if reportErrors && (checkMode&SignatureCheckModeStrictArity == 0) {
errorReporter(
diagnostics.Target_signature_provides_too_few_arguments_Expected_0_or_more_but_got_1,
sourceCount, c.getMinArgumentCount(target))
}
return TernaryFalse
}
Key design decisions:
- The check is scoped to method/constructor signatures only, not function assignments
or callbacks, so(x, y) => voidaccepting(x) => {}still works as before. - Optional parameters in the target are counted correctly via
getMinArgumentCount,
som(x, y?)implemented bym(x) {}still compiles. - It mirrors the existing
--strictfamily of checks in spirit — off by default,
opt-in viaSignatureCheckModeStrictArity, or enforced directly in the npm build.
Shipped as @topce/native-preview v7.0.0-dev.20260711.3:
https://www.npmjs.com/package/@topce/native-preview/v/7.0.0-dev.20260711.3
Patch against microsoft/typescript-go — relater.go, +22 lines, no deletions.
Curious if others have hit this in production. I've seen it cause silent API mismatches
between interface contracts and implementations a few times.