Error on too many parameters for iterator method (#60321)

This commit is contained in:
Ron Buckton 2024-10-22 16:00:58 -04:00 коммит произвёл GitHub
Родитель aa411acab7
Коммит e25abe34ae
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 156 добавлений и 23 удалений

Просмотреть файл

@ -171,6 +171,7 @@ import {
EnumMember,
EnumType,
equateValues,
ErrorOutputContainer,
escapeLeadingUnderscores,
escapeString,
EvaluatorResult,
@ -20608,7 +20609,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
expr: Expression | undefined,
headMessage: DiagnosticMessage | undefined,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
): boolean {
if (isTypeRelatedTo(source, target, relation)) return true;
if (!errorNode || !elaborateError(expr, source, target, relation, headMessage, containingMessageChain, errorOutputContainer)) {
@ -20628,7 +20629,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
relation: Map<string, RelationComparisonResult>,
headMessage: DiagnosticMessage | undefined,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
): boolean {
if (!node || isOrHasGenericConditional(target)) return false;
if (
@ -20672,7 +20673,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
relation: Map<string, RelationComparisonResult>,
headMessage: DiagnosticMessage | undefined,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
): boolean {
const callSignatures = getSignaturesOfType(source, SignatureKind.Call);
const constructSignatures = getSignaturesOfType(source, SignatureKind.Construct);
@ -20705,7 +20706,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
): boolean {
// Don't elaborate blocks
if (isBlock(node.body)) {
@ -20796,7 +20797,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
) {
// Assignability failure - check each prop individually, and if that fails, fall back on the bad error span
let reportedError = false;
@ -20876,7 +20877,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
) {
const tupleOrArrayLikeTargetParts = filterType(target, isArrayOrTupleLikeType);
const nonTupleOrArrayLikeTargetParts = filterType(target, t => !isArrayOrTupleLikeType(t));
@ -20978,7 +20979,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
) {
let result = elaborateElementwise(generateJsxAttributes(node), source, target, relation, containingMessageChain, errorOutputContainer);
let invalidTextDiagnostic: DiagnosticMessage | undefined;
@ -21092,7 +21093,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
) {
if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false;
if (isTupleLikeType(source)) {
@ -21139,7 +21140,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
target: Type,
relation: Map<string, RelationComparisonResult>,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined,
errorOutputContainer: ErrorOutputContainer | undefined,
) {
if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false;
return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation, containingMessageChain, errorOutputContainer);
@ -21637,7 +21638,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
errorNode: Node | undefined,
headMessage?: DiagnosticMessage,
containingMessageChain?: () => DiagnosticMessageChain | undefined,
errorOutputContainer?: { errors?: Diagnostic[]; skipLogging?: boolean; },
errorOutputContainer?: ErrorOutputContainer,
): boolean {
let errorInfo: DiagnosticMessageChain | undefined;
let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined;
@ -35186,7 +35187,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
checkMode: CheckMode,
reportErrors: boolean,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; },
errorOutputContainer: ErrorOutputContainer,
) {
// Stateless function components can have maximum of three arguments: "props", "context", and "updater".
// However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
@ -35302,7 +35303,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
inferenceContext: InferenceContext | undefined,
): readonly Diagnostic[] | undefined {
const errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } = { errors: undefined, skipLogging: true };
const errorOutputContainer: ErrorOutputContainer = { errors: undefined, skipLogging: true };
if (isJsxCallLike(node)) {
if (!checkApplicableSignatureForJsxCallLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
@ -44934,7 +44935,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (!(type.flags & TypeFlags.Union)) {
const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode ? { errors: undefined } : undefined;
const errorOutputContainer: ErrorOutputContainer | undefined = errorNode ? { errors: undefined, skipLogging: true } : undefined;
const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer);
if (iterationTypes === noIterationTypes) {
if (errorNode) {
@ -44959,7 +44960,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
let allIterationTypes: IterationTypes[] | undefined;
for (const constituent of (type as UnionType).types) {
const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode ? { errors: undefined } : undefined;
const errorOutputContainer: ErrorOutputContainer | undefined = errorNode ? { errors: undefined } : undefined;
const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer);
if (iterationTypes === noIterationTypes) {
if (errorNode) {
@ -45010,7 +45011,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterable` instead.
*/
function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined) {
function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined) {
if (isTypeAny(type)) {
return anyIterationTypes;
}
@ -45152,19 +45153,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterable` instead.
*/
function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) {
function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined, noCache: boolean) {
const method = getPropertyOfType(type, getPropertyNameForKnownSymbolName(resolver.iteratorSymbolName));
const methodType = method && !(method.flags & SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined;
if (isTypeAny(methodType)) {
return noCache ? anyIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes);
}
const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined;
if (!some(signatures)) {
const allSignatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined;
const validSignatures = filter(allSignatures, sig => getMinArgumentCount(sig) === 0);
if (!some(validSignatures)) {
if (errorNode && some(allSignatures)) {
checkTypeAssignableTo(type, resolver.getGlobalIterableType(/*reportErrors*/ true), errorNode, /*headMessage*/ undefined, /*containingMessageChain*/ undefined, errorOutputContainer);
}
return noCache ? noIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes);
}
const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature));
const iteratorType = getIntersectionType(map(validSignatures, getReturnTypeOfSignature));
const iterationTypes = getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) ?? noIterationTypes;
return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes);
}
@ -45193,7 +45198,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
* record is returned. Otherwise, `undefined` is returned.
*/
function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined) {
function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined) {
return getIterationTypesOfIteratorWorker(type, resolver, errorNode, errorOutputContainer, /*noCache*/ false);
}
@ -45206,7 +45211,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterator` instead.
*/
function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) {
function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined, noCache: boolean) {
if (isTypeAny(type)) {
return anyIterationTypes;
}
@ -45348,7 +45353,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
* record is returned. Otherwise, we return `undefined`.
*/
function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined): IterationTypes | undefined {
function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined): IterationTypes | undefined {
const method = getPropertyOfType(type, methodName as __String);
// Ignore 'return' or 'throw' if they are missing.
@ -45468,7 +45473,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterator` instead.
*/
function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) {
function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: ErrorOutputContainer | undefined, noCache: boolean) {
const iterationTypes = combineIterationTypes([
getIterationTypesOfMethod(type, resolver, "next", errorNode, errorOutputContainer),
getIterationTypesOfMethod(type, resolver, "return", errorNode, errorOutputContainer),

Просмотреть файл

@ -9981,6 +9981,12 @@ export interface TextChangeRange {
newLength: number;
}
/** @internal */
export interface ErrorOutputContainer {
errors?: Diagnostic[];
skipLogging?: boolean;
}
/** @internal */
export interface DiagnosticCollection {
// Adds a diagnostic to this diagnostic collection.

Просмотреть файл

@ -0,0 +1,32 @@
asyncIteratorExtraParameters.ts(11,27): error TS2504: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.
asyncIteratorExtraParameters.ts(13,12): error TS2504: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.
==== asyncIteratorExtraParameters.ts (2 errors) ====
// https://github.com/microsoft/TypeScript/issues/57130
const iter = {
async *[Symbol.asyncIterator](_: number) {
yield 0;
}
};
declare function g(...args: any): any;
async function* f() {
for await (const _ of iter);
~~~~
!!! error TS2504: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.
!!! related TS2322 asyncIteratorExtraParameters.ts:11:27: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' is not assignable to type 'AsyncIterable<T, TReturn, TNext>'.
Types of property '[Symbol.asyncIterator]' are incompatible.
Type '(_: number) => AsyncGenerator<number, void, unknown>' is not assignable to type '() => AsyncIterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
yield* iter;
~~~~
!!! error TS2504: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.
!!! related TS2322 asyncIteratorExtraParameters.ts:13:12: Type '{ [Symbol.asyncIterator](_: number): AsyncGenerator<number, void, unknown>; }' is not assignable to type 'AsyncIterable<T, TReturn, TNext>'.
Types of property '[Symbol.asyncIterator]' are incompatible.
Type '(_: number) => AsyncGenerator<number, void, unknown>' is not assignable to type '() => AsyncIterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
}

Просмотреть файл

@ -0,0 +1,50 @@
iteratorExtraParameters.ts(11,21): error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
iteratorExtraParameters.ts(13,12): error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
iteratorExtraParameters.ts(15,9): error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
iteratorExtraParameters.ts(17,10): error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
==== iteratorExtraParameters.ts (4 errors) ====
// https://github.com/microsoft/TypeScript/issues/57130
const iter = {
*[Symbol.iterator](_: number) {
yield 0;
}
};
declare function g(...args: any): any;
function* f() {
for (const _ of iter);
~~~~
!!! error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2322 iteratorExtraParameters.ts:11:21: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' is not assignable to type 'Iterable<T, TReturn, TNext>'.
Types of property '[Symbol.iterator]' are incompatible.
Type '(_: number) => Generator<number, void, unknown>' is not assignable to type '() => Iterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
yield* iter;
~~~~
!!! error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2322 iteratorExtraParameters.ts:13:12: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' is not assignable to type 'Iterable<T, TReturn, TNext>'.
Types of property '[Symbol.iterator]' are incompatible.
Type '(_: number) => Generator<number, void, unknown>' is not assignable to type '() => Iterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
[...iter]
~~~~
!!! error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2322 iteratorExtraParameters.ts:15:9: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' is not assignable to type 'Iterable<T, TReturn, TNext>'.
Types of property '[Symbol.iterator]' are incompatible.
Type '(_: number) => Generator<number, void, unknown>' is not assignable to type '() => Iterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
g(...iter);
~~~~
!!! error TS2488: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2322 iteratorExtraParameters.ts:17:10: Type '{ [Symbol.iterator](_: number): Generator<number, void, unknown>; }' is not assignable to type 'Iterable<T, TReturn, TNext>'.
Types of property '[Symbol.iterator]' are incompatible.
Type '(_: number) => Generator<number, void, unknown>' is not assignable to type '() => Iterator<T, TReturn, TNext>'.
Target signature provides too few arguments. Expected 1 or more, but got 0.
}

Просмотреть файл

@ -0,0 +1,18 @@
// @target: esnext
// @noEmit: true
// @noTypesAndSymbols: true
// https://github.com/microsoft/TypeScript/issues/57130
const iter = {
async *[Symbol.asyncIterator](_: number) {
yield 0;
}
};
declare function g(...args: any): any;
async function* f() {
for await (const _ of iter);
yield* iter;
}

Просмотреть файл

@ -0,0 +1,22 @@
// @target: esnext
// @noEmit: true
// @noTypesAndSymbols: true
// https://github.com/microsoft/TypeScript/issues/57130
const iter = {
*[Symbol.iterator](_: number) {
yield 0;
}
};
declare function g(...args: any): any;
function* f() {
for (const _ of iter);
yield* iter;
[...iter]
g(...iter);
}