diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 4b9e3f8f1ea..6cc9e4cd7c8 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -29,7 +29,7 @@ If possible, please try testing the nightly version of TS to see if it's already For npm: `typescript@next` This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly -Note: The TypeScript Playground can be used to try older verions of TypeScript. +Note: The TypeScript Playground can be used to try older versions of TypeScript. Please keep and fill in the line that best applies: --> diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1659c486f6f..f2fb60dc5fc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -202,7 +202,8 @@ namespace ts { Source = 1 << 0, Target = 1 << 1, PropertyCheck = 1 << 2, - InPropertyCheck = 1 << 3, + UnionIntersectionCheck = 1 << 3, + InPropertyCheck = 1 << 4, } const enum MappedTypeModifiers { @@ -10637,6 +10638,10 @@ namespace ts { return type; } + function getIsLateCheckFlag(s: Symbol): CheckFlags { + return getCheckFlags(s) & CheckFlags.Late; + } + /** Resolve the members of a mapped type { [P in K]: T } */ function resolveMappedTypeMembers(type: MappedType) { const members: SymbolTable = createSymbolTable(); @@ -10695,8 +10700,9 @@ namespace ts { const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp)); const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; + const lateFlag: CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0; const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, - CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)); + lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)); prop.mappedType = type; prop.nameType = propNameType; prop.keyType = keyType; @@ -12951,7 +12957,7 @@ namespace ts { // is true for each of the synthesized type parameters. function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType { const arity = elementFlags.length; - const minLength = findLastIndex(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic))) + 1; + const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic))); let typeParameters: TypeParameter[] | undefined; const properties: Symbol[] = []; let combinedFlags: ElementFlags = 0; @@ -13008,89 +13014,90 @@ namespace ts { } function createNormalizedTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined) { - return target.objectFlags & ObjectFlags.Tuple && (target).combinedFlags & ElementFlags.Variadic ? - createNormalizedTupleType(target as TupleType, typeArguments!) : - createTypeReference(target, typeArguments); + return target.objectFlags & ObjectFlags.Tuple ? createNormalizedTupleType(target as TupleType, typeArguments!) : createTypeReference(target, typeArguments); } function createNormalizedTupleType(target: TupleType, elementTypes: readonly Type[]): Type { - // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z] - const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union))); - if (unionIndex >= 0) { - return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ? - mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) : - errorType; - } - // If there are no variadic elements with non-generic types, just create a type reference with the same target type. - const spreadIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic) && !(t.flags & TypeFlags.InstantiableNonPrimitive) && !isGenericMappedType(t)); - if (spreadIndex < 0) { + if (!(target.combinedFlags & ElementFlags.NonRequired)) { + // No need to normalize when we only have regular required elements return createTypeReference(target, elementTypes); } - // We have non-generic variadic elements that need normalization. + if (target.combinedFlags & ElementFlags.Variadic) { + // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z] + const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union))); + if (unionIndex >= 0) { + return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ? + mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) : + errorType; + } + } + // We have optional, rest, or variadic elements that may need normalizing. Normalization ensures that all variadic + // elements are generic and that the tuple type has one of the following layouts, disregarding variadic elements: + // (1) Zero or more required elements, followed by zero or more optional elements, followed by zero or one rest element. + // (2) Zero or more required elements, followed by a rest element, followed by zero or more required elements. + // In either layout, zero or more generic variadic elements may be present at any location. const expandedTypes: Type[] = []; const expandedFlags: ElementFlags[] = []; let expandedDeclarations: (NamedTupleMember | ParameterDeclaration)[] | undefined = []; - let optionalIndex = -1; - let restTypes: Type[] | undefined; + let lastRequiredIndex = -1; + let firstRestIndex = -1; + let lastOptionalOrRestIndex = -1; for (let i = 0; i < elementTypes.length; i++) { const type = elementTypes[i]; const flags = target.elementFlags[i]; if (flags & ElementFlags.Variadic) { if (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type)) { - // Generic variadic elements stay as they are (except following a rest element). - addElementOrRest(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]); + // Generic variadic elements stay as they are. + addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]); } else if (isTupleType(type)) { // Spread variadic elements with tuple types into the resulting tuple. - forEach(getTypeArguments(type), (t, n) => addElementOrRest(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n])); + forEach(getTypeArguments(type), (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n])); } else { // Treat everything else as an array type and create a rest element. - addElementOrRest(isArrayLikeType(type) && getIndexTypeOfType(type, IndexKind.Number) || errorType, ElementFlags.Rest, target.labeledElementDeclarations?.[i]); + addElement(isArrayLikeType(type) && getIndexTypeOfType(type, IndexKind.Number) || errorType, ElementFlags.Rest, target.labeledElementDeclarations?.[i]); } } else { // Copy other element kinds with no change. - addElementOrRest(type, flags, target.labeledElementDeclarations?.[i]); + addElement(type, flags, target.labeledElementDeclarations?.[i]); } } - if (restTypes) { - // Create a union of the collected rest element types. - expandedTypes[expandedTypes.length - 1] = getUnionType(restTypes); + // Turn optional elements preceding the last required element into required elements + for (let i = 0; i < lastRequiredIndex; i++) { + if (expandedFlags[i] & ElementFlags.Optional) expandedFlags[i] = ElementFlags.Required; + } + if (firstRestIndex >= 0 && firstRestIndex < lastOptionalOrRestIndex) { + // Turn elements between first rest and last optional/rest into a single rest element + expandedTypes[firstRestIndex] = getUnionType(sameMap(expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1), + (t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t)); + expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); + expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); + expandedDeclarations?.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); } const tupleTarget = getTupleTargetType(expandedFlags, target.readonly, expandedDeclarations); return tupleTarget === emptyGenericType ? emptyObjectType : expandedFlags.length ? createTypeReference(tupleTarget, expandedTypes) : tupleTarget; - function addElementOrRest(type: Type, flags: ElementFlags, declaration: NamedTupleMember | ParameterDeclaration | undefined) { - if (restTypes) { - // A rest element was previously added, so simply collect the type of this element. - restTypes.push(flags & ElementFlags.Variadic ? getIndexedAccessType(type, numberType) : type); + function addElement(type: Type, flags: ElementFlags, declaration: NamedTupleMember | ParameterDeclaration | undefined) { + if (flags & ElementFlags.Required) { + lastRequiredIndex = expandedFlags.length; + } + if (flags & ElementFlags.Rest && firstRestIndex < 0) { + firstRestIndex = expandedFlags.length; + } + if (flags & (ElementFlags.Optional | ElementFlags.Rest)) { + lastOptionalOrRestIndex = expandedFlags.length; + } + expandedTypes.push(type); + expandedFlags.push(flags); + if (expandedDeclarations && declaration) { + expandedDeclarations.push(declaration); } else { - if (flags & ElementFlags.Required && optionalIndex >= 0) { - // Turn preceding optional elements into required elements - for (let i = optionalIndex; i < expandedFlags.length; i++) { - if (expandedFlags[i] & ElementFlags.Optional) expandedFlags[i] = ElementFlags.Required; - } - optionalIndex = -1; - } - else if (flags & ElementFlags.Optional && optionalIndex < 0) { - optionalIndex = expandedFlags.length; - } - else if (flags & ElementFlags.Rest) { - // Start collecting element types when a rest element is added. - restTypes = [type]; - } - expandedTypes.push(type); - expandedFlags.push(flags); - if (expandedDeclarations && declaration) { - expandedDeclarations.push(declaration); - } - else { - expandedDeclarations = undefined; - } + expandedDeclarations = undefined; } } } @@ -13108,6 +13115,17 @@ namespace ts { getIndexType(type.target.readonly ? globalReadonlyArrayType : globalArrayType))); } + // Return count of starting consecutive tuple elements of the given kind(s) + function getStartElementCount(type: TupleType, flags: ElementFlags) { + const index = findIndex(type.elementFlags, f => !(f & flags)); + return index >= 0 ? index : type.elementFlags.length; + } + + // Return count of ending consecutive tuple elements of the given kind(s) + function getEndElementCount(type: TupleType, flags: ElementFlags) { + return type.elementFlags.length - findLastIndex(type.elementFlags, f => !(f & flags)) - 1; + } + function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type { const type = getTypeFromTypeNode(node.type); return strictNullChecks ? getOptionalType(type) : type; @@ -14758,7 +14776,7 @@ namespace ts { else if (isSpreadableProperty(prop)) { const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); const flags = SymbolFlags.Property | SymbolFlags.Optional; - const result = createSymbol(flags, prop.escapedName, readonly ? CheckFlags.Readonly : 0); + const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop); result.declarations = prop.declarations; result.nameType = getSymbolLinks(prop).nameType; @@ -14906,7 +14924,7 @@ namespace ts { return prop; } const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional); - const result = createSymbol(flags, prop.escapedName, readonly ? CheckFlags.Readonly : 0); + const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop); result.declarations = prop.declarations; result.nameType = getSymbolLinks(prop).nameType; @@ -17088,38 +17106,14 @@ namespace ts { // Note that these checks are specifically ordered to produce correct results. In particular, // we need to deconstruct unions before intersections (because unions are always at the top), // and we need to handle "each" relations before "some" relations for the same kind of type. - if (source.flags & TypeFlags.Union) { - result = relation === comparableRelation ? - someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState) : - eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState); + if (source.flags & TypeFlags.UnionOrIntersection || target.flags & TypeFlags.UnionOrIntersection) { + result = getConstituentCount(source) * getConstituentCount(target) >= 4 ? + recursiveTypeRelatedTo(source, target, reportErrors, intersectionState | IntersectionState.UnionIntersectionCheck) : + structuredTypeRelatedTo(source, target, reportErrors, intersectionState | IntersectionState.UnionIntersectionCheck); } - else { - if (target.flags & TypeFlags.Union) { - result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); - } - else if (target.flags & TypeFlags.Intersection) { - result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors, IntersectionState.Target); - } - else if (source.flags & TypeFlags.Intersection) { - // Check to see if any constituents of the intersection are immediately related to the target. - // - // Don't report errors though. Checking whether a constituent is related to the source is not actually - // useful and leads to some confusing error messages. Instead it is better to let the below checks - // take care of this, or to not elaborate at all. For instance, - // - // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors. - // - // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection - // than to report that 'D' is not assignable to 'A' or 'B'. - // - // - For a primitive type or type parameter (such as 'number = A & B') there is no point in - // breaking the intersection apart. - result = someTypeRelatedToType(source, target, /*reportErrors*/ false, IntersectionState.Source); - } - if (!result && (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable)) { - if (result = recursiveTypeRelatedTo(source, target, reportErrors, intersectionState)) { - resetErrorInfo(saveErrorInfo); - } + if (!result && !(source.flags & TypeFlags.Union) && (source.flags & (TypeFlags.StructuredOrInstantiable) || target.flags & TypeFlags.StructuredOrInstantiable)) { + if (result = recursiveTypeRelatedTo(source, target, reportErrors, intersectionState)) { + resetErrorInfo(saveErrorInfo); } } if (!result && source.flags & (TypeFlags.Intersection | TypeFlags.TypeParameter)) { @@ -17627,6 +17621,37 @@ namespace ts { if (intersectionState & IntersectionState.PropertyCheck) { return propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None); } + if (intersectionState & IntersectionState.UnionIntersectionCheck) { + // Note that these checks are specifically ordered to produce correct results. In particular, + // we need to deconstruct unions before intersections (because unions are always at the top), + // and we need to handle "each" relations before "some" relations for the same kind of type. + if (source.flags & TypeFlags.Union) { + return relation === comparableRelation ? + someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState & ~IntersectionState.UnionIntersectionCheck) : + eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState & ~IntersectionState.UnionIntersectionCheck); + } + if (target.flags & TypeFlags.Union) { + return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); + } + if (target.flags & TypeFlags.Intersection) { + return typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors, IntersectionState.Target); + } + // Source is an intersection. Check to see if any constituents of the intersection are immediately related + // to the target. + // + // Don't report errors though. Checking whether a constituent is related to the source is not actually + // useful and leads to some confusing error messages. Instead it is better to let the below checks + // take care of this, or to not elaborate at all. For instance, + // + // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors. + // + // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection + // than to report that 'D' is not assignable to 'A' or 'B'. + // + // - For a primitive type or type parameter (such as 'number = A & B') there is no point in + // breaking the intersection apart. + return someTypeRelatedToType(source, target, /*reportErrors*/ false, IntersectionState.Source); + } const flags = source.flags & target.flags; if (relation === identityRelation && !(flags & TypeFlags.Object)) { if (flags & TypeFlags.Index) { @@ -18397,48 +18422,60 @@ namespace ts { } return Ternary.False; } - const maxArity = Math.max(sourceArity, targetArity); - for (let i = 0; i < maxArity; i++) { - const targetFlags = i < targetArity ? target.target.elementFlags[i] : targetRestFlag; - const sourceFlags = isTupleType(source) && i < sourceArity ? source.target.elementFlags[i] : sourceRestFlag; - let canExcludeDiscriminants = !!excludedProperties; - if (sourceFlags && targetFlags) { - if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic) || - (sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable))) { - if (reportErrors) { - reportError(Diagnostics.Element_at_index_0_is_variadic_in_one_type_but_not_in_the_other, i); - } - return Ternary.False; + const sourceTypeArguments = getTypeArguments(source); + const targetTypeArguments = getTypeArguments(target); + const startCount = Math.min(isTupleType(source) ? getStartElementCount(source.target, ElementFlags.NonRest) : 0, getStartElementCount(target.target, ElementFlags.NonRest)); + const endCount = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.NonRest) : 0, targetRestFlag ? getEndElementCount(target.target, ElementFlags.NonRest) : 0); + let canExcludeDiscriminants = !!excludedProperties; + for (let i = 0; i < targetArity; i++) { + const sourceIndex = i < targetArity - endCount ? i : i + sourceArity - targetArity; + const sourceFlags = isTupleType(source) && (i < startCount || i >= targetArity - endCount) ? source.target.elementFlags[sourceIndex] : ElementFlags.Rest; + const targetFlags = target.target.elementFlags[i]; + if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic)) { + if (reportErrors) { + reportError(Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, i); } - if (targetFlags & ElementFlags.Required) { - if (!(sourceFlags & ElementFlags.Required)) { - if (reportErrors) { - reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, i, typeToString(source), typeToString(target)); - } - return Ternary.False; - } - } - // We can only exclude discriminant properties if we have not yet encountered a variable-length element. - if (canExcludeDiscriminants) { - if (sourceFlags & ElementFlags.Variable || targetFlags & ElementFlags.Variable) { - canExcludeDiscriminants = false; - } - if (canExcludeDiscriminants && excludedProperties?.has(("" + i) as __String)) { - continue; - } - } - const sourceType = getTypeArguments(source)[Math.min(i, sourceArity - 1)]; - const targetType = getTypeArguments(target)[Math.min(i, targetArity - 1)]; - const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : targetType; - const related = isRelatedTo(sourceType, targetCheckType, reportErrors, /*headMessage*/ undefined, intersectionState); - if (!related) { - if (reportErrors) { - reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, i); - } - return Ternary.False; - } - result &= related; + return Ternary.False; } + if (sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable)) { + if (reportErrors) { + reportError(Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourceIndex, i); + } + return Ternary.False; + } + if (targetFlags & ElementFlags.Required && !(sourceFlags & ElementFlags.Required)) { + if (reportErrors) { + reportError(Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, i); + } + return Ternary.False; + } + // We can only exclude discriminant properties if we have not yet encountered a variable-length element. + if (canExcludeDiscriminants) { + if (sourceFlags & ElementFlags.Variable || targetFlags & ElementFlags.Variable) { + canExcludeDiscriminants = false; + } + if (canExcludeDiscriminants && excludedProperties?.has(("" + i) as __String)) { + continue; + } + } + const sourceType = !isTupleType(source) ? sourceTypeArguments[0] : + i < startCount || i >= targetArity - endCount ? sourceTypeArguments[sourceIndex] : + getElementTypeOfSliceOfTupleType(source, startCount, endCount) || neverType; + const targetType = targetTypeArguments[i]; + const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : targetType; + const related = isRelatedTo(sourceType, targetCheckType, reportErrors, /*headMessage*/ undefined, intersectionState); + if (!related) { + if (reportErrors) { + if (i < startCount || i >= targetArity - endCount || sourceArity - startCount - endCount === 1) { + reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourceIndex, i); + } + else { + reportIncompatibleError(Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, startCount, sourceArity - endCount - 1, i); + } + } + return Ternary.False; + } + result &= related; } return result; } @@ -19404,10 +19441,6 @@ namespace ts { return restType && createArrayType(restType); } - function getEndLengthOfType(type: Type) { - return isTupleType(type) ? getTypeReferenceArity(type) - findLastIndex(type.target.elementFlags, f => !(f & (ElementFlags.Required | ElementFlags.Optional))) - 1 : 0; - } - function getElementTypeOfSliceOfTupleType(type: TupleTypeReference, index: number, endSkipCount = 0, writing = false) { const length = getTypeReferenceArity(type) - endSkipCount; if (index < length) { @@ -20724,20 +20757,17 @@ namespace ts { return; } const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const sourceRestType = !isTupleType(source) || sourceArity > 0 && source.target.elementFlags[sourceArity - 1] & ElementFlags.Rest ? - getTypeArguments(source)[sourceArity - 1] : undefined; - const endLength = !(target.target.combinedFlags & ElementFlags.Variable) ? 0 : - sourceRestType ? getEndLengthOfType(target) : - Math.min(getEndLengthOfType(source), getEndLengthOfType(target)); - const sourceEndLength = sourceRestType ? 0 : endLength; + const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, + target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); // Infer between starting fixed elements. for (let i = 0; i < startLength; i++) { inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); } - if (sourceRestType && sourceArity - startLength === 1) { + if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ElementFlags.Rest) { // Single rest element remains in source, infer from that to every element in target + const restType = getTypeArguments(source)[startLength]; for (let i = startLength; i < targetArity - endLength; i++) { - inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(sourceRestType) : sourceRestType, elementTypes[i]); + inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]); } } else { @@ -20747,20 +20777,20 @@ namespace ts { const targetInfo = getInferenceInfoForType(elementTypes[startLength]); if (targetInfo && targetInfo.impliedArity !== undefined) { // Infer slices from source based on implied arity of T. - inferFromTypes(sliceTupleType(source, startLength, sourceEndLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]); - inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, sourceEndLength), elementTypes[startLength + 1]); + inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]); + inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]); } } else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) { // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source. // If target ends in optional element(s), make a lower priority a speculative inference. const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional; - const sourceSlice = isTupleType(source) ? sliceTupleType(source, startLength, sourceEndLength) : createArrayType(sourceRestType!); + const sourceSlice = isTupleType(source) ? sliceTupleType(source, startLength, endLength) : createArrayType(getTypeArguments(source)[0]); inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0); } else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) { // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types. - const restType = isTupleType(source) ? getElementTypeOfSliceOfTupleType(source, startLength, sourceEndLength) : sourceRestType; + const restType = isTupleType(source) ? getElementTypeOfSliceOfTupleType(source, startLength, endLength) : getTypeArguments(source)[0]; if (restType) { inferFromTypes(restType, elementTypes[startLength]); } @@ -20768,7 +20798,7 @@ namespace ts { } // Infer between ending fixed elements for (let i = 0; i < endLength; i++) { - inferFromTypes(sourceRestType || getTypeArguments(source)[sourceArity - i - 1], elementTypes[targetArity - i - 1]); + inferFromTypes(getTypeArguments(source)[sourceArity - i - 1], elementTypes[targetArity - i - 1]); } return; } @@ -21587,6 +21617,10 @@ namespace ts { return changed ? mappedTypes && getUnionType(mappedTypes, noReductions ? UnionReduction.None : UnionReduction.Literal) : type; } + function getConstituentCount(type: Type) { + return type.flags & TypeFlags.UnionOrIntersection ? (type).types.length : 1; + } + function extractTypesOfKind(type: Type, kind: TypeFlags) { return filterType(type, t => (t.flags & kind) !== 0); } @@ -27243,7 +27277,11 @@ namespace ts { } if (restType) { const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined, checkMode); - const errorNode = reportErrors ? argCount < args.length ? args[argCount] : node : undefined; + const restArgCount = args.length - argCount; + const errorNode = !reportErrors ? undefined : + restArgCount === 0 ? node : + restArgCount === 1 ? args[argCount] : + setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end); if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) { Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); maybeAddMissingAwaitInfo(errorNode, spreadType, restType); @@ -29102,6 +29140,10 @@ namespace ts { return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined); } + // Return the number of parameters in a signature. The rest parameter, if present, counts as one + // parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and + // the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the + // latter example, the effective rest type is [...string[], boolean]. function getParameterCount(signature: Signature) { const length = signature.parameters.length; if (signatureHasRestParameter(signature)) { @@ -32250,8 +32292,7 @@ namespace ts { let seenOptionalElement = false; let seenRestElement = false; const hasNamedElement = some(elementTypes, isNamedTupleMember); - for (let i = 0; i < elementTypes.length; i++) { - const e = elementTypes[i]; + for (const e of elementTypes) { if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) { grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; @@ -32268,19 +32309,23 @@ namespace ts { } } else if (flags & ElementFlags.Rest) { + if (seenRestElement) { + grammarErrorOnNode(e, Diagnostics.A_rest_element_cannot_follow_another_rest_element); + break; + } seenRestElement = true; } else if (flags & ElementFlags.Optional) { + if (seenRestElement) { + grammarErrorOnNode(e, Diagnostics.An_optional_element_cannot_follow_a_rest_element); + break; + } seenOptionalElement = true; } else if (seenOptionalElement) { grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element); break; } - if (seenRestElement && i !== elementTypes.length - 1) { - grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type); - break; - } } forEach(node.elements, checkSourceElement); getTypeFromTypeNode(node); @@ -35764,7 +35809,7 @@ namespace ts { const implementedTypeNodes = getEffectiveImplementsTypeNodes(node); if (implementedTypeNodes) { for (const typeRefNode of implementedTypeNodes) { - if (!isEntityNameExpression(typeRefNode.expression)) { + if (!isEntityNameExpression(typeRefNode.expression) || isOptionalChain(typeRefNode.expression)) { error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(typeRefNode); @@ -36113,7 +36158,7 @@ namespace ts { checkObjectTypeForDuplicateDeclarations(node); } forEach(getInterfaceBaseTypeNodes(node), heritageElement => { - if (!isEntityNameExpression(heritageElement.expression)) { + if (!isEntityNameExpression(heritageElement.expression) || isOptionalChain(heritageElement.expression)) { error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(heritageElement); @@ -38758,7 +38803,10 @@ namespace ts { isOptionalParameter, moduleExportsSomeValue, isArgumentsLocalBinding, - getExternalModuleFileFromDeclaration, + getExternalModuleFileFromDeclaration: nodeIn => { + const node = getParseTreeNode(nodeIn, hasPossibleExternalModuleReference); + return node && getExternalModuleFileFromDeclaration(node); + }, getTypeReferenceDirectivesForEntityName, getTypeReferenceDirectivesForSymbol, isLiteralConstDeclaration, @@ -38919,7 +38967,7 @@ namespace ts { } } - function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode): SourceFile | undefined { + function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined { const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) : getExternalModuleName(declaration); const moduleSymbol = resolveExternalModuleNameWorker(specifier!, specifier!, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 37f12224c75..403d130cb4b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -843,10 +843,6 @@ "category": "Error", "code": 1255 }, - "A rest element must be last in a tuple type.": { - "category": "Error", - "code": 1256 - }, "A required element cannot follow an optional element.": { "category": "Error", "code": 1257 @@ -875,6 +871,14 @@ "category": "Error", "code": 1264 }, + "A rest element cannot follow another rest element.": { + "category": "Error", + "code": 1265 + }, + "An optional element cannot follow a rest element.": { + "category": "Error", + "code": 1266 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", @@ -2621,9 +2625,25 @@ "category": "Error", "code": 2621 }, - "Element at index {0} is variadic in one type but not in the other.": { + "Source provides no match for required element at position {0} in target.": { "category": "Error", - "code": 2622 + "code": 2623 + }, + "Source provides no match for variadic element at position {0} in target.": { + "category": "Error", + "code": 2624 + }, + "Variadic element at position {0} in source does not match element at position {1} in target.": { + "category": "Error", + "code": 2625 + }, + "Type at position {0} in source is not compatible with type at position {1} in target.": { + "category": "Error", + "code": 2626 + }, + "Type at positions {0} through {1} in source is not compatible with type at position {2} in target.": { + "category": "Error", + "code": 2627 }, "Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": { diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 0960509ae4d..8b18c3152e3 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -511,12 +511,12 @@ namespace ts { * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). * Otherwise, a new StringLiteral node representing the module name will be returned. */ - export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { - const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 - if (moduleName.kind === SyntaxKind.StringLiteral) { + export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { + const moduleName = getExternalModuleName(importNode); + if (moduleName && isStringLiteral(moduleName)) { return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) - || tryRenameExternalModule(factory, moduleName, sourceFile) - || factory.cloneNode(moduleName); + || tryRenameExternalModule(factory, moduleName, sourceFile) + || factory.cloneNode(moduleName); } return undefined; @@ -528,7 +528,7 @@ namespace ts { */ function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) { const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); - return rename && factory.createStringLiteral(rename); + return rename ? factory.createStringLiteral(rename) : undefined; } /** @@ -551,7 +551,7 @@ namespace ts { return undefined; } - function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { + function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); } diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 69fa41b2071..f9e539770dc 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -90,8 +90,6 @@ namespace ts { return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.VariableStatement: return visitVariableStatement(node as VariableStatement); - case SyntaxKind.ComputedPropertyName: - return visitComputedPropertyName(node as ComputedPropertyName); case SyntaxKind.PropertyAccessExpression: return visitPropertyAccessExpression(node as PropertyAccessExpression); case SyntaxKind.PrefixUnaryExpression: @@ -184,7 +182,7 @@ namespace ts { let node = visitEachChild(name, visitor, context); if (some(pendingExpressions)) { const expressions = pendingExpressions; - expressions.push(name.expression); + expressions.push(node.expression); pendingExpressions = []; node = factory.updateComputedPropertyName( node, diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 12871142561..d2f4917d50b 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -609,7 +609,10 @@ namespace ts { } function visitImportCallExpression(node: ImportCall): Expression { - const argument = visitNode(firstOrUndefined(node.arguments), moduleExpressionElementVisitor); + const externalModuleName = getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions); + const firstArgument = visitNode(firstOrUndefined(node.arguments), moduleExpressionElementVisitor); + // Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output. + const argument = externalModuleName && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) ? externalModuleName : firstArgument; const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis); switch (compilerOptions.module) { case ModuleKind.AMD: diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 5935a3e7f5e..a5e0c9bbbf4 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1495,13 +1495,17 @@ namespace ts { // } // }; // }); + const externalModuleName = getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions); + const firstArgument = visitNode(firstOrUndefined(node.arguments), destructuringAndImportCallVisitor); + // Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output. + const argument = externalModuleName && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) ? externalModuleName : firstArgument; return factory.createCallExpression( factory.createPropertyAccessExpression( contextObject, factory.createIdentifier("import") ), /*typeArguments*/ undefined, - some(node.arguments) ? [visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : [] + argument ? [argument] : [] ); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e17d3bbdedc..3680d49fcff 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4607,7 +4607,7 @@ namespace ts { isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; - getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile | undefined; + getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined; getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[] | undefined; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined; isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; @@ -5251,18 +5251,21 @@ namespace ts { } export const enum ElementFlags { - Required = 1 << 0, // T - Optional = 1 << 1, // T? - Rest = 1 << 2, // ...T[] - Variadic = 1 << 3, // ...T - Variable = Rest | Variadic, + Required = 1 << 0, // T + Optional = 1 << 1, // T? + Rest = 1 << 2, // ...T[] + Variadic = 1 << 3, // ...T + Fixed = Required | Optional, + Variable = Rest | Variadic, + NonRequired = Optional | Rest | Variadic, + NonRest = Required | Optional | Variadic, } export interface TupleType extends GenericType { elementFlags: readonly ElementFlags[]; - minLength: number; - fixedLength: number; - hasRestElement: boolean; + minLength: number; // Number of required or variadic elements + fixedLength: number; // Number of initial required or optional elements + hasRestElement: boolean; // True if tuple has any rest or variadic elements combinedFlags: ElementFlags; readonly: boolean; labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a50ca22095d..476a73f55c0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -907,6 +907,10 @@ namespace ts { } } + export function hasPossibleExternalModuleReference(node: Node): node is AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall { + return isAnyImportOrReExport(node) || isModuleDeclaration(node) || isImportTypeNode(node) || isImportCall(node); + } + export function isAnyImportOrReExport(node: Node): node is AnyImportOrReExport { return isAnyImportSyntax(node) || isExportDeclaration(node); } @@ -2426,7 +2430,7 @@ namespace ts { } } - export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression | undefined { + export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall): Expression | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: @@ -2435,6 +2439,8 @@ namespace ts { return node.moduleReference.kind === SyntaxKind.ExternalModuleReference ? node.moduleReference.expression : undefined; case SyntaxKind.ImportType: return isLiteralImportTypeNode(node) ? node.argument.literal : undefined; + case SyntaxKind.CallExpression: + return node.arguments[0]; default: return Debug.assertNever(node); } @@ -3065,14 +3071,7 @@ namespace ts { return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind); } - export type TriviaKind = - SyntaxKind.SingleLineCommentTrivia - | SyntaxKind.MultiLineCommentTrivia - | SyntaxKind.NewLineTrivia - | SyntaxKind.WhitespaceTrivia - | SyntaxKind.ShebangTrivia - | SyntaxKind.ConflictMarkerTrivia; - export function isTrivia(token: SyntaxKind): token is TriviaKind { + export function isTrivia(token: SyntaxKind): token is TriviaSyntaxKind { return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken; } @@ -3580,7 +3579,8 @@ namespace ts { } // TODO: Should prefix `++` and `--` be moved to the `Update` precedence? - // TODO: We are missing `TypeAssertionExpression` + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.TypeOfExpression: case SyntaxKind.VoidExpression: @@ -3602,6 +3602,9 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return OperatorPrecedence.Member; + case SyntaxKind.AsExpression: + return OperatorPrecedence.Relational; + case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: case SyntaxKind.Identifier: diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 82c019c03a3..def48d12b06 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -594,6 +594,10 @@ interface ImageEncodeOptions { type?: string; } +interface ImportMeta { + url?: string; +} + interface InputEventInit extends UIEventInit { data?: string | null; inputType?: string; @@ -611,7 +615,7 @@ interface IntersectionObserverEntryInit { } interface IntersectionObserverInit { - root?: Element | null; + root?: Element | Document | null; rootMargin?: string; threshold?: number | number[]; } @@ -642,6 +646,8 @@ interface KeyAlgorithm { } interface KeyboardEventInit extends EventModifierInit { + /** @deprecated */ + charCode?: number; code?: string; isComposing?: boolean; key?: string; @@ -1023,18 +1029,13 @@ interface PermissionDescriptor { name: PermissionName; } -interface PipeOptions { - preventAbort?: boolean; - preventCancel?: boolean; - preventClose?: boolean; - signal?: AbortSignal; -} - interface PointerEventInit extends MouseEventInit { + coalescedEvents?: PointerEvent[]; height?: number; isPrimary?: boolean; pointerId?: number; pointerType?: string; + predictedEvents?: PointerEvent[]; pressure?: number; tangentialPressure?: number; tiltX?: number; @@ -1138,7 +1139,16 @@ interface PushSubscriptionOptionsInit { interface QueuingStrategy { highWaterMark?: number; - size?: QueuingStrategySizeCallback; + size?: QueuingStrategySize; +} + +interface QueuingStrategyInit { + /** + * Creates a new ByteLengthQueuingStrategy with the provided high water mark. + * + * Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw. + */ + highWaterMark: number; } interface RTCAnswerOptions extends RTCOfferAnswerOptions { @@ -1239,17 +1249,36 @@ interface RTCIceCandidatePair { interface RTCIceCandidatePairStats extends RTCStats { availableIncomingBitrate?: number; availableOutgoingBitrate?: number; + bytesDiscardedOnSend?: number; bytesReceived?: number; bytesSent?: number; + circuitBreakerTriggerCount?: number; + consentExpiredTimestamp?: number; + consentRequestsSent?: number; + currentRoundTripTime?: number; + currentRtt?: number; + firstRequestTimestamp?: number; + lastPacketReceivedTimestamp?: number; + lastPacketSentTimestamp?: number; + lastRequestTimestamp?: number; + lastResponseTimestamp?: number; localCandidateId?: string; nominated?: boolean; + packetsDiscardedOnSend?: number; + packetsReceived?: number; + packetsSent?: number; priority?: number; - readable?: boolean; remoteCandidateId?: string; - roundTripTime?: number; + requestsReceived?: number; + requestsSent?: number; + responsesReceived?: number; + responsesSent?: number; + retransmissionsReceived?: number; + retransmissionsSent?: number; state?: RTCStatsIceCandidatePairState; + totalRoundTripTime?: number; + totalRtt?: number; transportId?: string; - writable?: boolean; } interface RTCIceGatherOptions { @@ -1487,9 +1516,9 @@ interface RTCSsrcRange { } interface RTCStats { - id: string; - timestamp: number; - type: RTCStatsType; + id?: string; + timestamp?: number; + type?: RTCStatsType; } interface RTCStatsEventInit extends EventInit { @@ -1507,25 +1536,43 @@ interface RTCTrackEventInit extends EventInit { } interface RTCTransportStats extends RTCStats { - activeConnection?: boolean; bytesReceived?: number; bytesSent?: number; + dtlsCipher?: string; + dtlsState?: RTCDtlsTransportState; + iceRole?: RTCIceRole; localCertificateId?: string; + packetsReceived?: number; + packetsSent?: number; remoteCertificateId?: string; rtcpTransportStatsId?: string; + selectedCandidatePairChanges?: number; selectedCandidatePairId?: string; + srtpCipher?: string; + tlsGroup?: string; + tlsVersion?: string; } -interface ReadableStreamReadDoneResult { +interface ReadableStreamDefaultReadDoneResult { done: true; - value?: T; + value?: undefined; } -interface ReadableStreamReadValueResult { +interface ReadableStreamDefaultReadValueResult { done: false; value: T; } +interface ReadableWritablePair { + readable: ReadableStream; + /** + * Provides a convenient, chainable way of piping this readable stream through a transform stream (or any other { writable, readable } pair). It simply pipes the stream into the writable side of the supplied pair, and returns the readable side for further use. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + */ + writable: WritableStream; +} + interface RegistrationOptions { scope?: string; type?: WorkerType; @@ -1587,6 +1634,10 @@ interface RequestInit { window?: any; } +interface ResizeObserverOptions { + box?: ResizeObserverBoxOptions; +} + interface ResponseInit { headers?: HeadersInit; status?: number; @@ -1700,6 +1751,16 @@ interface ShareData { url?: string; } +interface SpeechRecognitionErrorEventInit extends EventInit { + error: SpeechRecognitionErrorCode; + message?: string; +} + +interface SpeechRecognitionEventInit extends EventInit { + resultIndex?: number; + results: SpeechRecognitionResultList; +} + interface SpeechSynthesisErrorEventInit extends SpeechSynthesisEventInit { error: SpeechSynthesisErrorCode; } @@ -1746,6 +1807,30 @@ interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformat arrayOfDomainStrings?: string[]; } +interface StreamPipeOptions { + preventAbort?: boolean; + preventCancel?: boolean; + /** + * Pipes this readable stream to a given writable stream destination. The way in which the piping process behaves under various error conditions can be customized with a number of passed options. It returns a promise that fulfills when the piping process completes successfully, or rejects if any errors were encountered. + * + * Piping a stream will lock it for the duration of the pipe, preventing any other consumer from acquiring a reader. + * + * Errors and closures of the source and destination streams propagate as follows: + * + * An error in this source readable stream will abort destination, unless preventAbort is truthy. The returned promise will be rejected with the source's error, or with any error that occurs during aborting the destination. + * + * An error in destination will cancel this source readable stream, unless preventCancel is truthy. The returned promise will be rejected with the destination's error, or with any error that occurs during canceling the source. + * + * When this source readable stream closes, destination will be closed, unless preventClose is truthy. The returned promise will be fulfilled once this process completes, unless an error is encountered while closing the destination, in which case it will be rejected with that error. + * + * If destination starts out closed or closing, this source readable stream will be canceled, unless preventCancel is true. The returned promise will be rejected with an error indicating piping to a closed stream failed, or with any error that occurs during canceling the source. + * + * The signal option can be set to an AbortSignal to allow aborting an ongoing pipe operation via the corresponding AbortController. In this case, this source readable stream will be canceled, and destination aborted, unless the respective options preventCancel or preventAbort are set. + */ + preventClose?: boolean; + signal?: AbortSignal; +} + interface TextDecodeOptions { stream?: boolean; } @@ -1789,10 +1874,10 @@ interface TrackEventInit extends EventInit { } interface Transformer { - flush?: TransformStreamDefaultControllerCallback; + flush?: TransformerFlushCallback; readableType?: undefined; - start?: TransformStreamDefaultControllerCallback; - transform?: TransformStreamDefaultControllerTransformCallback; + start?: TransformerStartCallback; + transform?: TransformerTransformCallback; writableType?: undefined; } @@ -1812,26 +1897,18 @@ interface ULongRange { min?: number; } -interface UnderlyingByteSource { - autoAllocateChunkSize?: number; - cancel?: ReadableStreamErrorCallback; - pull?: ReadableByteStreamControllerCallback; - start?: ReadableByteStreamControllerCallback; - type: "bytes"; -} - interface UnderlyingSink { - abort?: WritableStreamErrorCallback; - close?: WritableStreamDefaultControllerCloseCallback; - start?: WritableStreamDefaultControllerStartCallback; + abort?: UnderlyingSinkAbortCallback; + close?: UnderlyingSinkCloseCallback; + start?: UnderlyingSinkStartCallback; type?: undefined; - write?: WritableStreamDefaultControllerWriteCallback; + write?: UnderlyingSinkWriteCallback; } interface UnderlyingSource { - cancel?: ReadableStreamErrorCallback; - pull?: ReadableStreamDefaultControllerCallback; - start?: ReadableStreamDefaultControllerCallback; + cancel?: UnderlyingSourceCancelCallback; + pull?: UnderlyingSourcePullCallback; + start?: UnderlyingSourceStartCallback; type?: undefined; } @@ -2320,7 +2397,9 @@ declare var AudioParamMap: { new(): AudioParamMap; }; -/** The Web Audio API events that occur when a ScriptProcessorNode input buffer is ready to be processed. */ +/** The Web Audio API events that occur when a ScriptProcessorNode input buffer is ready to be processed. + * @deprecated As of the August 29 2014 Web Audio API spec publication, this feature has been marked as deprecated, and is soon to be replaced by AudioWorklet. + */ interface AudioProcessingEvent extends Event { readonly inputBuffer: AudioBuffer; readonly outputBuffer: AudioBuffer; @@ -2563,13 +2642,13 @@ declare var BroadcastChannel: { /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface ByteLengthQueuingStrategy extends QueuingStrategy { - highWaterMark: number; - size(chunk: ArrayBufferView): number; + readonly highWaterMark: number; + readonly size: QueuingStrategySize; } declare var ByteLengthQueuingStrategy: { prototype: ByteLengthQueuingStrategy; - new(options: { highWaterMark: number }): ByteLengthQueuingStrategy; + new(init: QueuingStrategyInit): ByteLengthQueuingStrategy; }; /** A CDATA section that can be used within XML to include extended portions of unescaped text. The symbols < and & don’t need escaping as they normally do when inside a CDATA section. */ @@ -3614,13 +3693,13 @@ declare var ConvolverNode: { /** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface CountQueuingStrategy extends QueuingStrategy { - highWaterMark: number; - size(chunk: any): 1; + readonly highWaterMark: number; + readonly size: QueuingStrategySize; } declare var CountQueuingStrategy: { prototype: CountQueuingStrategy; - new(options: { highWaterMark: number }): CountQueuingStrategy; + new(init: QueuingStrategyInit): CountQueuingStrategy; }; interface Credential { @@ -4680,6 +4759,7 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad createEvent(eventInterface: "SVGZoomEvents"): SVGZoomEvent; createEvent(eventInterface: "SecurityPolicyViolationEvent"): SecurityPolicyViolationEvent; createEvent(eventInterface: "ServiceWorkerMessageEvent"): ServiceWorkerMessageEvent; + createEvent(eventInterface: "SpeechRecognitionErrorEvent"): SpeechRecognitionErrorEvent; createEvent(eventInterface: "SpeechRecognitionEvent"): SpeechRecognitionEvent; createEvent(eventInterface: "SpeechSynthesisErrorEvent"): SpeechSynthesisErrorEvent; createEvent(eventInterface: "SpeechSynthesisEvent"): SpeechSynthesisEvent; @@ -4747,14 +4827,14 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad exitPointerLock(): void; getAnimations(): Animation[]; /** - * Returns a reference to the first object with the specified value of the ID or NAME attribute. - * @param elementId String that specifies the ID value. Case-insensitive. + * Returns a reference to the first object with the specified value of the ID attribute. + * @param elementId String that specifies the ID value. */ - getElementById(elementId: string): HTMLElement | null; + getElementById(elementId: string): E | null; /** * Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classNames. The classNames argument is interpreted as a space-separated list of classes. */ - getElementsByClassName(classNames: string): HTMLCollectionOf; + getElementsByClassName(classNames: string): HTMLCollectionOf; /** * Gets a collection of objects based on the value of the NAME or ID attribute. * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute. @@ -4929,6 +5009,7 @@ interface DocumentEvent { createEvent(eventInterface: "SVGZoomEvents"): SVGZoomEvent; createEvent(eventInterface: "SecurityPolicyViolationEvent"): SecurityPolicyViolationEvent; createEvent(eventInterface: "ServiceWorkerMessageEvent"): ServiceWorkerMessageEvent; + createEvent(eventInterface: "SpeechRecognitionErrorEvent"): SpeechRecognitionErrorEvent; createEvent(eventInterface: "SpeechRecognitionEvent"): SpeechRecognitionEvent; createEvent(eventInterface: "SpeechSynthesisErrorEvent"): SpeechSynthesisErrorEvent; createEvent(eventInterface: "SpeechSynthesisEvent"): SpeechSynthesisEvent; @@ -4949,7 +5030,7 @@ interface DocumentEvent { /** A minimal document object that has no parent. It is used as a lightweight version of Document that stores a segment of a document structure comprised of nodes just like a standard document. The key difference is that because the document fragment isn't part of the active document tree structure, changes made to the fragment don't affect the document, cause reflow, or incur any performance impact that can occur when changes are made. */ interface DocumentFragment extends Node, NonElementParentNode, ParentNode { readonly ownerDocument: Document; - getElementById(elementId: string): HTMLElement | null; + getElementById(elementId: string): E | null; } declare var DocumentFragment: { @@ -5057,7 +5138,6 @@ interface ElementEventMap { /** Element is the most general base class from which all objects in a Document inherit. It only has methods and properties common to all kinds of elements. More specific classes inherit from Element. */ interface Element extends Node, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable { - readonly assignedSlot: HTMLSlotElement | null; readonly attributes: NamedNodeMap; /** * Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. @@ -5136,7 +5216,7 @@ interface Element extends Node, Animatable, ChildNode, InnerHTML, NonDocumentTyp /** * Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classNames. The classNames argument is interpreted as a space-separated list of classes. */ - getElementsByClassName(classNames: string): HTMLCollectionOf; + getElementsByClassName(classNames: string): HTMLCollectionOf; getElementsByTagName(qualifiedName: K): HTMLCollectionOf; getElementsByTagName(qualifiedName: K): HTMLCollectionOf; getElementsByTagName(qualifiedName: string): HTMLCollectionOf; @@ -5612,24 +5692,7 @@ declare var GamepadPose: { }; interface GenericTransformStream { - /** - * Returns a readable stream whose chunks are strings resulting from running encoding's decoder on the chunks written to writable. - */ readonly readable: ReadableStream; - /** - * Returns a writable stream which accepts [AllowShared] BufferSource chunks and runs them through encoding's decoder before making them available to readable. - * - * Typically this will be used via the pipeThrough() method on a ReadableStream source. - * - * ``` - * var decoder = new TextDecoderStream(encoding); - * byteReadable - * .pipeThrough(decoder) - * .pipeTo(textWritable); - * ``` - * - * If the error mode is "fatal" and encoding's decoder returns error, both readable and writable will be errored with a TypeError. - */ readonly writable: WritableStream; } @@ -5693,6 +5756,7 @@ interface GlobalEventHandlersEventMap { "animationiteration": AnimationEvent; "animationstart": AnimationEvent; "auxclick": MouseEvent; + "beforeinput": InputEvent; "blur": FocusEvent; "cancel": Event; "canplay": Event; @@ -5700,6 +5764,9 @@ interface GlobalEventHandlersEventMap { "change": Event; "click": MouseEvent; "close": Event; + "compositionend": CompositionEvent; + "compositionstart": CompositionEvent; + "compositionupdate": CompositionEvent; "contextmenu": MouseEvent; "cuechange": Event; "dblclick": MouseEvent; @@ -6604,6 +6671,7 @@ interface HTMLElement extends Element, DocumentAndElementEventHandlers, ElementC readonly offsetParent: Element | null; readonly offsetTop: number; readonly offsetWidth: number; + readonly parentElement: HTMLElement | null; spellcheck: boolean; title: string; translate: boolean; @@ -7339,7 +7407,7 @@ interface HTMLInputElement extends HTMLElement { * @param end The offset into the text field for the end of the selection. * @param direction The direction in which the selection is performed. */ - setSelectionRange(start: number, end: number, direction?: "forward" | "backward" | "none"): void; + setSelectionRange(start: number | null, end: number | null, direction?: "forward" | "backward" | "none"): void; /** * Decrements a range input control's value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control's step value multiplied by the parameter's value. * @param n Value to decrement the value by. @@ -8635,7 +8703,6 @@ declare var HTMLTableElement: { }; interface HTMLTableHeaderCellElement extends HTMLTableCellElement { - scope: string; addEventListener(type: K, listener: (this: HTMLTableHeaderCellElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: HTMLTableHeaderCellElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -8846,7 +8913,7 @@ interface HTMLTextAreaElement extends HTMLElement { * @param end The offset into the text field for the end of the selection. * @param direction The direction in which the selection is performed. */ - setSelectionRange(start: number, end: number, direction?: "forward" | "backward" | "none"): void; + setSelectionRange(start: number | null, end: number | null, direction?: "forward" | "backward" | "none"): void; addEventListener(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -9613,7 +9680,7 @@ declare var InputEvent: { /** provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. */ interface IntersectionObserver { - readonly root: Element | null; + readonly root: Element | Document | null; readonly rootMargin: string; readonly thresholds: ReadonlyArray; disconnect(): void; @@ -10552,7 +10619,8 @@ declare var MouseEvent: { new(type: string, eventInitDict?: MouseEventInit): MouseEvent; }; -/** Provides event properties that are specific to modifications to the Document Object Model (DOM) hierarchy and nodes. */ +/** Provides event properties that are specific to modifications to the Document Object Model (DOM) hierarchy and nodes. + * @deprecated DOM4 [DOM] provides a new mechanism using a MutationObserver interface which addresses the use cases that mutation events solve, but in a more performant manner. Thus, this specification describes mutation events for reference and completeness of legacy behavior, but deprecates the use of the MutationEvent interface. */ interface MutationEvent extends Event { readonly attrChange: number; readonly attrName: string; @@ -10797,7 +10865,7 @@ interface Node extends EventTarget { /** * Returns the parent element. */ - readonly parentElement: HTMLElement | null; + readonly parentElement: Element | null; /** * Returns the parent. */ @@ -11030,7 +11098,6 @@ declare var NodeList: { }; interface NodeListOf extends NodeList { - length: number; item(index: number): TNode; /** * Performs the specified action for each node in an list. @@ -11056,7 +11123,7 @@ interface NonElementParentNode { /** * Returns the first element within node's descendants whose ID is elementId. */ - getElementById(elementId: string): Element | null; + getElementById(elementId: string): E | null; } interface NotificationEventMap { @@ -11539,7 +11606,9 @@ declare var PerformanceMeasure: { new(): PerformanceMeasure; }; -/** The legacy PerformanceNavigation interface represents information about how the navigation to the current document was done. */ +/** The legacy PerformanceNavigation interface represents information about how the navigation to the current document was done. + * @deprecated This interface is deprecated in the Navigation Timing Level 2 specification. Please use the PerformanceNavigationTiming interface instead. + */ interface PerformanceNavigation { readonly redirectCount: number; readonly type: number; @@ -11629,7 +11698,9 @@ declare var PerformanceResourceTiming: { new(): PerformanceResourceTiming; }; -/** A legacy interface kept for backwards compatibility and contains properties that offer performance timing information for various events which occur during the loading and use of the current page. You get a PerformanceTiming object describing your page using the window.performance.timing property. */ +/** A legacy interface kept for backwards compatibility and contains properties that offer performance timing information for various events which occur during the loading and use of the current page. You get a PerformanceTiming object describing your page using the window.performance.timing property. + * @deprecated This interface is deprecated in the Navigation Timing Level 2 specification. Please use the PerformanceNavigationTiming interface instead. + */ interface PerformanceTiming { readonly connectEnd: number; readonly connectStart: number; @@ -11772,6 +11843,8 @@ interface PointerEvent extends MouseEvent { readonly tiltY: number; readonly twist: number; readonly width: number; + getCoalescedEvents(): PointerEvent[]; + getPredictedEvents(): PointerEvent[]; } declare var PointerEvent: { @@ -12475,64 +12548,26 @@ declare var Range: { toString(): string; }; -interface ReadableByteStreamController { - readonly byobRequest: ReadableStreamBYOBRequest | undefined; - readonly desiredSize: number | null; - close(): void; - enqueue(chunk: ArrayBufferView): void; - error(error?: any): void; -} - -declare var ReadableByteStreamController: { - prototype: ReadableByteStreamController; - new(): ReadableByteStreamController; -}; - /** This Streams API interface represents a readable stream of byte data. The Fetch API offers a concrete instance of a ReadableStream through the body property of a Response object. */ interface ReadableStream { readonly locked: boolean; cancel(reason?: any): Promise; - getReader(options: { mode: "byob" }): ReadableStreamBYOBReader; getReader(): ReadableStreamDefaultReader; - pipeThrough({ writable, readable }: { writable: WritableStream, readable: ReadableStream }, options?: PipeOptions): ReadableStream; - pipeTo(dest: WritableStream, options?: PipeOptions): Promise; + pipeThrough(transform: ReadableWritablePair, options?: StreamPipeOptions): ReadableStream; + pipeTo(dest: WritableStream, options?: StreamPipeOptions): Promise; tee(): [ReadableStream, ReadableStream]; } declare var ReadableStream: { prototype: ReadableStream; - new(underlyingSource: UnderlyingByteSource, strategy?: { highWaterMark?: number, size?: undefined }): ReadableStream; new(underlyingSource?: UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; }; -interface ReadableStreamBYOBReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - read(view: T): Promise>; - releaseLock(): void; -} - -declare var ReadableStreamBYOBReader: { - prototype: ReadableStreamBYOBReader; - new(): ReadableStreamBYOBReader; -}; - -interface ReadableStreamBYOBRequest { - readonly view: ArrayBufferView; - respond(bytesWritten: number): void; - respondWithNewView(view: ArrayBufferView): void; -} - -declare var ReadableStreamBYOBRequest: { - prototype: ReadableStreamBYOBRequest; - new(): ReadableStreamBYOBRequest; -}; - interface ReadableStreamDefaultController { readonly desiredSize: number | null; close(): void; enqueue(chunk: R): void; - error(error?: any): void; + error(e?: any): void; } declare var ReadableStreamDefaultController: { @@ -12540,29 +12575,21 @@ declare var ReadableStreamDefaultController: { new(): ReadableStreamDefaultController; }; -interface ReadableStreamDefaultReader { - readonly closed: Promise; - cancel(reason?: any): Promise; - read(): Promise>; +interface ReadableStreamDefaultReader extends ReadableStreamGenericReader { + read(): Promise>; releaseLock(): void; } declare var ReadableStreamDefaultReader: { prototype: ReadableStreamDefaultReader; - new(): ReadableStreamDefaultReader; + new(stream: ReadableStream): ReadableStreamDefaultReader; }; -interface ReadableStreamReader { - cancel(): Promise; - read(): Promise>; - releaseLock(): void; +interface ReadableStreamGenericReader { + readonly closed: Promise; + cancel(reason?: any): Promise; } -declare var ReadableStreamReader: { - prototype: ReadableStreamReader; - new(): ReadableStreamReader; -}; - /** This Fetch API interface represents a resource request. */ interface Request extends Body { /** @@ -12633,6 +12660,39 @@ declare var Request: { new(input: RequestInfo, init?: RequestInit): Request; }; +interface ResizeObserver { + disconnect(): void; + observe(target: Element, options?: ResizeObserverOptions): void; + unobserve(target: Element): void; +} + +declare var ResizeObserver: { + prototype: ResizeObserver; + new(callback: ResizeObserverCallback): ResizeObserver; +}; + +interface ResizeObserverEntry { + readonly borderBoxSize: ReadonlyArray; + readonly contentBoxSize: ReadonlyArray; + readonly contentRect: DOMRectReadOnly; + readonly target: Element; +} + +declare var ResizeObserverEntry: { + prototype: ResizeObserverEntry; + new(): ResizeObserverEntry; +}; + +interface ResizeObserverSize { + readonly blockSize: number; + readonly inlineSize: number; +} + +declare var ResizeObserverSize: { + prototype: ResizeObserverSize; + new(): ResizeObserverSize; +}; + /** This Fetch API interface represents the response to a request. */ interface Response extends Body { readonly headers: Headers; @@ -12992,7 +13052,9 @@ interface SVGElement extends Element, DocumentAndElementEventHandlers, DocumentA /** @deprecated */ readonly className: any; readonly ownerSVGElement: SVGSVGElement | null; + readonly parentElement: SVGElement | null; readonly viewportElement: SVGElement | null; + getElementsByClassName(classNames: string): HTMLCollectionOf; addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -13580,6 +13642,7 @@ interface SVGForeignObjectElement extends SVGGraphicsElement { readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; + getElementsByClassName(classNames: string): HTMLCollectionOf; addEventListener(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; removeEventListener(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; @@ -14383,7 +14446,7 @@ interface SVGSVGElement extends SVGGraphicsElement, DocumentEvent, SVGFitToViewB forceRedraw(): void; getComputedStyle(elt: Element, pseudoElt?: string | null): CSSStyleDeclaration; getCurrentTime(): number; - getElementById(elementId: string): Element; + getElementById(elementId: string): E | null; getEnclosureList(rect: SVGRect, referenceElement: SVGElement | null): NodeListOf; getIntersectionList(rect: SVGRect, referenceElement: SVGElement | null): NodeListOf; pauseAnimations(): void; @@ -14457,7 +14520,7 @@ declare var SVGStringList: { }; /** Corresponds to the SVG