Skip to content

Commit ad55bbc

Browse files
committed
Merge branch 'master' into broadening-optional-spread-heuristic
2 parents 4ea2b2c + dbba8b3 commit ad55bbc

15 files changed

+251
-34
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18608,7 +18608,11 @@ namespace ts {
1860818608
continue;
1860918609
}
1861018610
if (kind === IndexKind.String || isNumericLiteralName(prop.escapedName)) {
18611-
const related = isRelatedTo(getTypeOfSymbol(prop), target, reportErrors);
18611+
const propType = getTypeOfSymbol(prop);
18612+
const type = propType.flags & TypeFlags.Undefined || !(kind === IndexKind.String && prop.flags & SymbolFlags.Optional)
18613+
? propType
18614+
: getTypeWithFacts(propType, TypeFacts.NEUndefined);
18615+
const related = isRelatedTo(type, target, reportErrors);
1861218616
if (!related) {
1861318617
if (reportErrors) {
1861418618
reportError(Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop));

src/lib/dom.generated.d.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ interface ImageEncodeOptions {
595595
}
596596

597597
interface ImportMeta {
598-
url?: string;
598+
url: string;
599599
}
600600

601601
interface InputEventInit extends UIEventInit {
@@ -4830,11 +4830,11 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad
48304830
* Returns a reference to the first object with the specified value of the ID attribute.
48314831
* @param elementId String that specifies the ID value.
48324832
*/
4833-
getElementById<E extends Element = HTMLElement>(elementId: string): E | null;
4833+
getElementById(elementId: string): HTMLElement | null;
48344834
/**
48354835
* 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.
48364836
*/
4837-
getElementsByClassName<E extends Element = HTMLElement>(classNames: string): HTMLCollectionOf<E>;
4837+
getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;
48384838
/**
48394839
* Gets a collection of objects based on the value of the NAME or ID attribute.
48404840
* @param elementName Gets a collection of objects based on the value of the NAME or ID attribute.
@@ -5030,7 +5030,7 @@ interface DocumentEvent {
50305030
/** 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. */
50315031
interface DocumentFragment extends Node, NonElementParentNode, ParentNode {
50325032
readonly ownerDocument: Document;
5033-
getElementById<E extends Element = HTMLElement>(elementId: string): E | null;
5033+
getElementById(elementId: string): HTMLElement | null;
50345034
}
50355035

50365036
declare var DocumentFragment: {
@@ -5216,7 +5216,7 @@ interface Element extends Node, Animatable, ChildNode, InnerHTML, NonDocumentTyp
52165216
/**
52175217
* 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.
52185218
*/
5219-
getElementsByClassName<E extends Element = HTMLElement>(classNames: string): HTMLCollectionOf<E>;
5219+
getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;
52205220
getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
52215221
getElementsByTagName<K extends keyof SVGElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<SVGElementTagNameMap[K]>;
52225222
getElementsByTagName(qualifiedName: string): HTMLCollectionOf<Element>;
@@ -6671,7 +6671,6 @@ interface HTMLElement extends Element, DocumentAndElementEventHandlers, ElementC
66716671
readonly offsetParent: Element | null;
66726672
readonly offsetTop: number;
66736673
readonly offsetWidth: number;
6674-
readonly parentElement: HTMLElement | null;
66756674
spellcheck: boolean;
66766675
title: string;
66776676
translate: boolean;
@@ -10865,7 +10864,7 @@ interface Node extends EventTarget {
1086510864
/**
1086610865
* Returns the parent element.
1086710866
*/
10868-
readonly parentElement: Element | null;
10867+
readonly parentElement: HTMLElement | null;
1086910868
/**
1087010869
* Returns the parent.
1087110870
*/
@@ -11123,7 +11122,7 @@ interface NonElementParentNode {
1112311122
/**
1112411123
* Returns the first element within node's descendants whose ID is elementId.
1112511124
*/
11126-
getElementById<E extends Element = HTMLElement>(elementId: string): E | null;
11125+
getElementById(elementId: string): Element | null;
1112711126
}
1112811127

1112911128
interface NotificationEventMap {
@@ -13052,9 +13051,7 @@ interface SVGElement extends Element, DocumentAndElementEventHandlers, DocumentA
1305213051
/** @deprecated */
1305313052
readonly className: any;
1305413053
readonly ownerSVGElement: SVGSVGElement | null;
13055-
readonly parentElement: SVGElement | null;
1305613054
readonly viewportElement: SVGElement | null;
13057-
getElementsByClassName<E extends Element = SVGElement>(classNames: string): HTMLCollectionOf<E>;
1305813055
addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
1305913056
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
1306013057
removeEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
@@ -13642,7 +13639,6 @@ interface SVGForeignObjectElement extends SVGGraphicsElement {
1364213639
readonly width: SVGAnimatedLength;
1364313640
readonly x: SVGAnimatedLength;
1364413641
readonly y: SVGAnimatedLength;
13645-
getElementsByClassName<E extends Element = HTMLElement>(classNames: string): HTMLCollectionOf<E>;
1364613642
addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
1364713643
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
1364813644
removeEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
@@ -14446,7 +14442,7 @@ interface SVGSVGElement extends SVGGraphicsElement, DocumentEvent, SVGFitToViewB
1444614442
forceRedraw(): void;
1444714443
getComputedStyle(elt: Element, pseudoElt?: string | null): CSSStyleDeclaration;
1444814444
getCurrentTime(): number;
14449-
getElementById<E extends Element = HTMLElement>(elementId: string): E | null;
14445+
getElementById(elementId: string): Element;
1445014446
getEnclosureList(rect: SVGRect, referenceElement: SVGElement | null): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;
1445114447
getIntersectionList(rect: SVGRect, referenceElement: SVGElement | null): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;
1445214448
pauseAnimations(): void;

tests/baselines/reference/copyrightWithNewLine1.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import model = require("./greeter")
99
var el = document.getElementById('content');
1010
>el : HTMLElement
1111
>document.getElementById('content') : HTMLElement
12-
>document.getElementById : <E extends Element = HTMLElement>(elementId: string) => E
12+
>document.getElementById : (elementId: string) => HTMLElement
1313
>document : Document
14-
>getElementById : <E extends Element = HTMLElement>(elementId: string) => E
14+
>getElementById : (elementId: string) => HTMLElement
1515
>'content' : "content"
1616

1717
var greeter = new model.Greeter(el);

tests/baselines/reference/copyrightWithoutNewLine1.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import model = require("./greeter")
88
var el = document.getElementById('content');
99
>el : HTMLElement
1010
>document.getElementById('content') : HTMLElement
11-
>document.getElementById : <E extends Element = HTMLElement>(elementId: string) => E
11+
>document.getElementById : (elementId: string) => HTMLElement
1212
>document : Document
13-
>getElementById : <E extends Element = HTMLElement>(elementId: string) => E
13+
>getElementById : (elementId: string) => HTMLElement
1414
>'content' : "content"
1515

1616
var greeter = new model.Greeter(el);

tests/baselines/reference/genericMethodOverspecialization.types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ declare var document: Document;
2121

2222
interface Document {
2323
getElementById(elementId: string): HTMLElement;
24-
>getElementById : { <E extends Element = HTMLElement>(elementId: string): E; (elementId: string): HTMLElement; }
24+
>getElementById : { (elementId: string): HTMLElement; (elementId: string): HTMLElement; }
2525
>elementId : string
2626
}
2727

@@ -36,9 +36,9 @@ var elements = names.map(function (name) {
3636

3737
return document.getElementById(name);
3838
>document.getElementById(name) : HTMLElement
39-
>document.getElementById : { <E extends Element = HTMLElement>(elementId: string): E; (elementId: string): HTMLElement; }
39+
>document.getElementById : { (elementId: string): HTMLElement; (elementId: string): HTMLElement; }
4040
>document : Document
41-
>getElementById : { <E extends Element = HTMLElement>(elementId: string): E; (elementId: string): HTMLElement; }
41+
>getElementById : { (elementId: string): HTMLElement; (elementId: string): HTMLElement; }
4242
>name : string
4343

4444
});

tests/baselines/reference/intersectionsOfLargeUnions.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ export function assertNodeProperty<
7474
>tagName : T
7575

7676
node[prop];
77-
>node[prop] : ((null & ElementTagNameMap[T]) | (Node & ElementTagNameMap[T]))[P]
78-
>node : (null & ElementTagNameMap[T]) | (Node & ElementTagNameMap[T])
77+
>node[prop] : ElementTagNameMap[T][P]
78+
>node : ElementTagNameMap[T]
7979
>prop : P
8080
}
8181
}

tests/baselines/reference/intersectionsOfLargeUnions2.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ tests/cases/compiler/intersectionsOfLargeUnions2.ts(31,15): error TS2536: Type '
1010
interface ElementTagNameMap {
1111
~~~~~~~~~~~~~~~~~
1212
!!! error TS2300: Duplicate identifier 'ElementTagNameMap'.
13-
!!! related TS6203 /.ts/lib.dom.d.ts:19590:6: 'ElementTagNameMap' was also declared here.
13+
!!! related TS6203 /.ts/lib.dom.d.ts:19586:6: 'ElementTagNameMap' was also declared here.
1414
[index: number]: HTMLElement
1515
}
1616

tests/baselines/reference/intersectionsOfLargeUnions2.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ export function assertNodeProperty<
8888
>tagName : T
8989

9090
node[prop];
91-
>node[prop] : ((null & ElementTagNameMap[T]) | (Node & ElementTagNameMap[T]))[P]
92-
>node : (null & ElementTagNameMap[T]) | (Node & ElementTagNameMap[T])
91+
>node[prop] : ElementTagNameMap[T][P]
92+
>node : ElementTagNameMap[T]
9393
>prop : P
9494
}
9595
}

tests/baselines/reference/mappedTypeRecursiveInference.types

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/optionalPropertyAssignableToStringIndexSignature.ts(6,1): error TS2322: Type '{ k1: string | undefined; }' is not assignable to type '{ [key: string]: string; }'.
2+
Property 'k1' is incompatible with index signature.
3+
Type 'string | undefined' is not assignable to type 'string'.
4+
Type 'undefined' is not assignable to type 'string'.
5+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/optionalPropertyAssignableToStringIndexSignature.ts(10,1): error TS2322: Type '{ 1?: string | undefined; }' is not assignable to type '{ [key: number]: string; }'.
6+
Property '1' is incompatible with index signature.
7+
Type 'string | undefined' is not assignable to type 'string'.
8+
Type 'undefined' is not assignable to type 'string'.
9+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/optionalPropertyAssignableToStringIndexSignature.ts(13,5): error TS2322: Type '{ k1?: undefined; }' is not assignable to type '{ [key: string]: string; }'.
10+
Property 'k1' is incompatible with index signature.
11+
Type 'undefined' is not assignable to type 'string'.
12+
13+
14+
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/optionalPropertyAssignableToStringIndexSignature.ts (3 errors) ====
15+
declare let optionalProperties: { k1?: string };
16+
declare let undefinedProperties: { k1: string | undefined };
17+
18+
declare let stringDictionary: { [key: string]: string };
19+
stringDictionary = optionalProperties; // ok
20+
stringDictionary = undefinedProperties; // error
21+
~~~~~~~~~~~~~~~~
22+
!!! error TS2322: Type '{ k1: string | undefined; }' is not assignable to type '{ [key: string]: string; }'.
23+
!!! error TS2322: Property 'k1' is incompatible with index signature.
24+
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'.
25+
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
26+
27+
declare let probablyArray: { [key: number]: string };
28+
declare let numberLiteralKeys: { 1?: string };
29+
probablyArray = numberLiteralKeys; // error
30+
~~~~~~~~~~~~~
31+
!!! error TS2322: Type '{ 1?: string | undefined; }' is not assignable to type '{ [key: number]: string; }'.
32+
!!! error TS2322: Property '1' is incompatible with index signature.
33+
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'.
34+
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
35+
36+
declare let optionalUndefined: { k1?: undefined };
37+
let dict: { [key: string]: string } = optionalUndefined; // error
38+
~~~~
39+
!!! error TS2322: Type '{ k1?: undefined; }' is not assignable to type '{ [key: string]: string; }'.
40+
!!! error TS2322: Property 'k1' is incompatible with index signature.
41+
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
42+
43+
function f<T>() {
44+
let optional: { k1?: T } = undefined!;
45+
let dict: { [key: string]: T | number } = optional; // ok
46+
}
47+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [optionalPropertyAssignableToStringIndexSignature.ts]
2+
declare let optionalProperties: { k1?: string };
3+
declare let undefinedProperties: { k1: string | undefined };
4+
5+
declare let stringDictionary: { [key: string]: string };
6+
stringDictionary = optionalProperties; // ok
7+
stringDictionary = undefinedProperties; // error
8+
9+
declare let probablyArray: { [key: number]: string };
10+
declare let numberLiteralKeys: { 1?: string };
11+
probablyArray = numberLiteralKeys; // error
12+
13+
declare let optionalUndefined: { k1?: undefined };
14+
let dict: { [key: string]: string } = optionalUndefined; // error
15+
16+
function f<T>() {
17+
let optional: { k1?: T } = undefined!;
18+
let dict: { [key: string]: T | number } = optional; // ok
19+
}
20+
21+
22+
//// [optionalPropertyAssignableToStringIndexSignature.js]
23+
"use strict";
24+
stringDictionary = optionalProperties; // ok
25+
stringDictionary = undefinedProperties; // error
26+
probablyArray = numberLiteralKeys; // error
27+
var dict = optionalUndefined; // error
28+
function f() {
29+
var optional = undefined;
30+
var dict = optional; // ok
31+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
=== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/optionalPropertyAssignableToStringIndexSignature.ts ===
2+
declare let optionalProperties: { k1?: string };
3+
>optionalProperties : Symbol(optionalProperties, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 0, 11))
4+
>k1 : Symbol(k1, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 0, 33))
5+
6+
declare let undefinedProperties: { k1: string | undefined };
7+
>undefinedProperties : Symbol(undefinedProperties, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 1, 11))
8+
>k1 : Symbol(k1, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 1, 34))
9+
10+
declare let stringDictionary: { [key: string]: string };
11+
>stringDictionary : Symbol(stringDictionary, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 3, 11))
12+
>key : Symbol(key, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 3, 33))
13+
14+
stringDictionary = optionalProperties; // ok
15+
>stringDictionary : Symbol(stringDictionary, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 3, 11))
16+
>optionalProperties : Symbol(optionalProperties, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 0, 11))
17+
18+
stringDictionary = undefinedProperties; // error
19+
>stringDictionary : Symbol(stringDictionary, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 3, 11))
20+
>undefinedProperties : Symbol(undefinedProperties, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 1, 11))
21+
22+
declare let probablyArray: { [key: number]: string };
23+
>probablyArray : Symbol(probablyArray, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 7, 11))
24+
>key : Symbol(key, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 7, 30))
25+
26+
declare let numberLiteralKeys: { 1?: string };
27+
>numberLiteralKeys : Symbol(numberLiteralKeys, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 8, 11))
28+
>1 : Symbol(1, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 8, 32))
29+
30+
probablyArray = numberLiteralKeys; // error
31+
>probablyArray : Symbol(probablyArray, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 7, 11))
32+
>numberLiteralKeys : Symbol(numberLiteralKeys, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 8, 11))
33+
34+
declare let optionalUndefined: { k1?: undefined };
35+
>optionalUndefined : Symbol(optionalUndefined, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 11, 11))
36+
>k1 : Symbol(k1, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 11, 32))
37+
38+
let dict: { [key: string]: string } = optionalUndefined; // error
39+
>dict : Symbol(dict, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 12, 3))
40+
>key : Symbol(key, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 12, 13))
41+
>optionalUndefined : Symbol(optionalUndefined, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 11, 11))
42+
43+
function f<T>() {
44+
>f : Symbol(f, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 12, 56))
45+
>T : Symbol(T, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 14, 11))
46+
47+
let optional: { k1?: T } = undefined!;
48+
>optional : Symbol(optional, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 15, 4))
49+
>k1 : Symbol(k1, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 15, 16))
50+
>T : Symbol(T, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 14, 11))
51+
>undefined : Symbol(undefined)
52+
53+
let dict: { [key: string]: T | number } = optional; // ok
54+
>dict : Symbol(dict, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 16, 4))
55+
>key : Symbol(key, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 16, 14))
56+
>T : Symbol(T, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 14, 11))
57+
>optional : Symbol(optional, Decl(optionalPropertyAssignableToStringIndexSignature.ts, 15, 4))
58+
}
59+

0 commit comments

Comments
 (0)