Skip to content

Panic: index out of range [-1] on type predicate parameter mismatch #2121

@techfreaque

Description

@techfreaque

Description

tsgo panics when a type predicate references a parameter name that doesn't match the function parameter.

Reproduction

type TypeA = { kind: 'a' };
type TypeB = { kind: 'b' };
type UnionType = TypeA | TypeB;

function isTypeA(
  _value: UnionType
): value is TypeA {  // "value" doesn't match parameter "_value"
  return true;
}

function test(input: UnionType): void {
  if (isTypeA(input)) {
    console.log(input.kind);
  }
}

Run: tsgo --noEmit

Expected

TypeScript error or graceful handling (like tsc does).

Actual

npx tsgo --noEmit --project tsconfig.json
panic: runtime error: index out of range [-1]

goroutine 231 [running]:
github.com/microsoft/typescript-go/internal/checker.(*Checker).getTypePredicateArgument(0xc000e20500?, 0xc000f38ae0, 0xc00014e098?)
        github.com/microsoft/typescript-go/internal/checker/flow.go:2409 +0xac
github.com/microsoft/typescript-go/internal/checker.(*Checker).narrowTypeByTypePredicate(0xc0005a1908, 0xc000316ae0, 0xc00062e900, 0xc000f38ae0, 0x7f360cdde5c0?, 0x1)
        github.com/microsoft/typescript-go/internal/checker/flow.go:307 +0x75
github.com/microsoft/typescript-go/internal/checker.(*Checker).narrowTypeByCallExpression(0xc0005a1908, 0xc000316ae0, 0xc00062e900, 0xc000152000, 0x1)
        github.com/microsoft/typescript-go/internal/checker/flow.go:442 +0xf0
github.com/microsoft/typescript-go/internal/checker.(*Checker).narrowType(0xc0005a1908, 0xc000316ae0, 0xc00062e900, 0xc000152000, 0x1)
        github.com/microsoft/typescript-go/internal/checker/flow.go:390 +0x254
github.com/microsoft/typescript-go/internal/checker.(*Checker).getTypeAtFlowCondition(0xc0005a1908, 0xc000316ae0, 0xc0002eaf20)
        github.com/microsoft/typescript-go/internal/checker/flow.go:356 +0x106
github.com/microsoft/typescript-go/internal/checker.(*Checker).getTypeAtFlowNode(0xc0005a1908, 0xc000316ae0, 0xc0005a85b0?)
        github.com/microsoft/typescript-go/internal/checker/flow.go:154 +0x412
github.com/microsoft/typescript-go/internal/checker.(*Checker).getFlowTypeOfReferenceEx(0xc0005a1908, 0xc00014e170, 0xc00062e900, 0xc00062e900, 0xc00014a0b0, 0xc00012216c?)
        github.com/microsoft/typescript-go/internal/checker/flow.go:96 +0x18f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkIdentifier(0xc0005a1908, 0xc00014e170, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:10851 +0xe9f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionWorker(0xc0005a1908, 0xc00014e170, 0x14e0e0?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7515 +0x1af
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionEx(0xc0005a1908, 0xc00014e170, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7345 +0x52
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpression(...)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7338
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkNonNullExpression(0xc0005a1908, 0xc00014e170)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7190 +0x1f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkPropertyAccessExpression(0xc0005a1908, 0xc000152108, 0x0, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:10923 +0x48
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionWorker(0xc0005a1908, 0xc000152108, 0x1520b0?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7548 +0x2f7
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionEx(0xc0005a1908, 0xc000152108, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7345 +0x52
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpression(...)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7338
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveUntypedCall(0xc0005a1908, 0xc000152058?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:9767 +0x1b2
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveErrorCall(...)
        github.com/microsoft/typescript-go/internal/checker/checker.go:9774
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveCallExpression(0xc0005a1908, 0xc000152058, 0x0, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:8362 +0x235
github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveSignature(0xc0005a2060?, 0xef7180?, 0xc000152058?, 0x826d2e?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:8303 +0x46
github.com/microsoft/typescript-go/internal/checker.(*Checker).getResolvedSignature(0xc0005a1908, 0xc000152058, 0x0, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:8275 +0xd8
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkCallExpression(0xc0005a1908, 0xc000152058, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:8171 +0x4f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionWorker(0xc0005a1908, 0xc000152058, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7557 +0x2df
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionEx(0xc0005a1908, 0xc000152058, 0x0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7345 +0x52
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpression(...)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7338
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkExpressionStatement(0xc0005a1908, 0xc000136180)
        github.com/microsoft/typescript-go/internal/checker/checker.go:7116 +0x36
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElementWorker(0xc0005a1908, 0xc000136180)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2254 +0x27e
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElement(0xc0005a1908, 0x0?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2169 +0x65
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElements(0xc0005a1908, {0xc00013a058, 0x1, 0x0?})
        github.com/microsoft/typescript-go/internal/checker/checker.go:2159 +0x2d
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkBlock(0xc0005a1908, 0xc000138120)
        github.com/microsoft/typescript-go/internal/checker/checker.go:3696 +0x145
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElementWorker(0xc0005a1908, 0xc000138120)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2250 +0x345
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElement(0xc0005a1908, 0xc000152000?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2169 +0x65
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkIfStatement(0xc0005a1908, 0xc000152160)
        github.com/microsoft/typescript-go/internal/checker/checker.go:3708 +0xad
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElementWorker(0xc0005a1908, 0xc000152160)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2256 +0x28a
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElement(0xc0005a1908, 0xc0007ffc08?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2169 +0x65
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElements(0xc0005a1908, {0xc00013a060, 0x1, 0xc0007ffc28?})
        github.com/microsoft/typescript-go/internal/checker/checker.go:2159 +0x2d
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkBlock(0xc0005a1908, 0xc000154000)
        github.com/microsoft/typescript-go/internal/checker/checker.go:3693 +0xfc
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElementWorker(0xc0005a1908, 0xc000154000)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2250 +0x345
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElement(0xc0005a1908, 0xc00029a000?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2169 +0x65
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkFunctionOrMethodDeclaration(0xc0005a1908, 0xc00014a0b0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:3348 +0x138
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkFunctionDeclaration(0xc0005a1908, 0xc00014a0b0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:3309 +0x1d
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElementWorker(0xc0005a1908, 0xc00014a0b0)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2248 +0x31f
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElement(0xc0005a1908, 0xc000b1e630?)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2169 +0x65
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceElements(0xc0005a1908, {0xc000146050, 0x5, 0xc000200040?})
        github.com/microsoft/typescript-go/internal/checker/checker.go:2159 +0x2d
github.com/microsoft/typescript-go/internal/checker.(*Checker).checkSourceFile(0xc0005a1908, {0xef1108, 0x155a2a0}, 0xc000156008)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2131 +0x119
github.com/microsoft/typescript-go/internal/checker.(*Checker).CheckSourceFile(0xc0005a1908, {0xef1108, 0x155a2a0}, 0xc000156008)
        github.com/microsoft/typescript-go/internal/checker/checker.go:2120 +0x5e
github.com/microsoft/typescript-go/internal/compiler.(*Program).getDiagnosticsHelper.(*Program).CheckSourceFiles.func1-range1(0xc000578601?)
        github.com/microsoft/typescript-go/internal/compiler/program.go:358 +0x94
github.com/microsoft/typescript-go/internal/compiler.(*checkerPool).Files.func1(0xc00033fa00)
        github.com/microsoft/typescript-go/internal/compiler/checkerpool.go:110 +0x88
github.com/microsoft/typescript-go/internal/compiler.(*Program).getDiagnosticsHelper.(*Program).CheckSourceFiles.func1(0xc000558908?, 0xc0005a1908)
        github.com/microsoft/typescript-go/internal/compiler/program.go:356 +0x112
github.com/microsoft/typescript-go/internal/compiler.(*checkerPool).ForEachCheckerParallel.func1()
        github.com/microsoft/typescript-go/internal/compiler/checkerpool.go:99 +0xc9
github.com/microsoft/typescript-go/internal/core.(*parallelWorkGroup).Queue.func1()
        github.com/microsoft/typescript-go/internal/core/workgroup.go:40 +0x13
sync.(*WaitGroup).Go.func1()
        sync/waitgroup.go:239 +0x4a
created by sync.(*WaitGroup).Go in goroutine 1
        sync/waitgroup.go:237 +0x73

Environment

  • tsgo: latest
  • TypeScript: 5.9.3
  • OS: Linux

Root Cause

getTypePredicateArgument (flow.go:2409) doesn't validate parameter existence before array access, resulting in index -1.

Suggested Fix

Validate parameter name exists before accessing parameter list, return error instead of panicking.

Minimal Reproduction Repository

https://github.com/techfreaque/tsgo_bug-reproduction

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions