Skip to content

SC1090 false positive: String(value) after typeof value === 'number' narrowing (union with object arms, 0.0.36 regression) #402

Description

@somarlyonks

Summary

String(value) on a union narrowed via typeof value === 'number' inside a for...in loop with a continue guard is rejected:

error SC1090: string conversions of unions with object arms (narrow first: ...) are not supported yet

The value is provably a number at that point. The same code compiled under 0.0.36.

Reproduction

type RelayHeaders = Record<string, string | string[] | number | undefined>

function relayHeaders (source: RelayHeaders, strip: Set<string>): Record<string, string> {
    const headers: Record<string, string> = {}
    for (const name in source) {
        const value = source[name]
        if (value === undefined || strip.has(name.toLowerCase())) continue
        if (typeof value === 'string') {
            headers[name] = value
        } else if (typeof value === 'number') {
            headers[name] = String(value)
        } else {
            headers[name] = value.join(', ')
        }
    }
    return headers
}

console.log(relayHeaders({a: 1, b: ['x', 'y']}, new Set(['c'])))

Actual

repro.ts:10:36 - error SC1090: string conversions of unions with object arms (narrow first: check a discriminant field, or compare with '!== undefined'/'!== null' for unit arms) are not supported yet

Expected

value is narrowed to number in the typeof value === 'number' branch, so String(value) should compile.

Workaround

Avoid the conversion by handling the array arm with Array.isArray and assigning the remaining primitive directly (also lets the value type drop the number arm if the source never carries numbers):

if (Array.isArray(value)) headers[name] = value.join(', ')
else headers[name] = value

Environment

  • scriptc 0.1.4
  • Node v24.14.0
  • macOS (Darwin arm64)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions