Files
scriptc/tests/corpus/8504-array-spread-widened-source.ts
T
Malte UblandClaude Opus 5.5 41364d9c08 Spread wider-than-runtime iterables in array literals and push/unshift
`[...maybe]` over a source the checker typed wider than the iterable it
holds at run time (`T | undefined` from an indexed read under
indexed-access strictness, an optional local) and `push(...value)` over
an untyped or widened source were SC1090 refusals. They now drain through
the checked iterator walk, validating each element into the target slot,
and throw Node's not-iterable TypeError for null/undefined.

`widenedIterableType` recognises a union of exactly one iterable arm plus
unit arms; `checkedIteratorPack` is exported so the array-method spread
path reuses the same walk.

Corpus 8504 covers `[...digit]` from a `string | undefined`, a `[...any]`
array literal, a `push(...any)`, and
`push(...(provider.x ?? []))`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:37:08 -07:00

40 lines
1.3 KiB
TypeScript

// Array spreads of sources the checker types wider than the iterable they
// hold: a `string | undefined` indexed read, and an untyped value. Node
// iterates whatever the value is; each element validates into the literal's
// element slot.
function expand(hex: string): string[] {
const digit: string | undefined = hex[1];
return [...digit];
}
console.log(JSON.stringify(expand("#0f0")));
console.log(JSON.stringify(expand("#abcdef")));
function doubled(hex: string): string {
const digits = [...hex[1]].map((digit) => digit + digit).join("");
return digits;
}
console.log(doubled("#0f0"));
interface Item {
api: string;
id: number;
}
function collect(source: any): Item[] {
return [...source];
}
console.log(JSON.stringify(collect([{ api: "a", id: 1 }, { api: "b", id: 2 }])));
function pushAll(target: Item[], source: any): number {
return target.push(...source);
}
const items: Item[] = [{ api: "seed", id: 0 }];
console.log(pushAll(items, [{ api: "c", id: 3 }]), JSON.stringify(items));
function collectStrings(provider: any): string[] {
const triggerCharacters: string[] = [];
triggerCharacters.push(...(provider.triggerCharacters ?? []));
return triggerCharacters;
}
console.log(JSON.stringify(collectStrings({ triggerCharacters: ["@", "#"] })));
console.log(JSON.stringify(collectStrings({})));