Skip to content

Commit ba0720e

Browse files
committed
Merge branch 'master' into disable-probing-for-nongeneric-instances
2 parents efc9478 + 2888510 commit ba0720e

20 files changed

+1149
-6
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11062,7 +11062,13 @@ namespace ts {
1106211062
return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));
1106311063
}
1106411064
if (flags & TypeFlags.Substitution) {
11065-
return instantiateType((<SubstitutionType>type).typeVariable, mapper);
11065+
const maybeVariable = instantiateType((<SubstitutionType>type).typeVariable, mapper);
11066+
if (maybeVariable.flags & TypeFlags.TypeVariable) {
11067+
return getSubstitutionType(maybeVariable as TypeVariable, instantiateType((<SubstitutionType>type).substitute, mapper));
11068+
}
11069+
else {
11070+
return maybeVariable;
11071+
}
1106611072
}
1106711073
return type;
1106811074
}
@@ -12781,6 +12787,11 @@ namespace ts {
1278112787
else if (isReadonlyArrayType(target) ? isArrayType(source) || isTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
1278212788
return isRelatedTo(getIndexTypeOfType(source, IndexKind.Number) || anyType, getIndexTypeOfType(target, IndexKind.Number) || anyType, reportErrors);
1278312789
}
12790+
// Consider a fresh empty object literal type "closed" under the subtype relationship - this way `{} <- {[idx: string]: any} <- fresh({})`
12791+
// and not `{} <- fresh({}) <- {[idx: string]: any}`
12792+
else if (relation === subtypeRelation && isEmptyObjectType(target) && getObjectFlags(target) & ObjectFlags.FreshLiteral && !isEmptyObjectType(source)) {
12793+
return Ternary.False;
12794+
}
1278412795
// Even if relationship doesn't hold for unions, intersections, or generic type references,
1278512796
// it may hold in a structural comparison.
1278612797
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
@@ -14475,6 +14486,9 @@ namespace ts {
1447514486
}
1447614487
}
1447714488
}
14489+
else if (target.flags & TypeFlags.Substitution) {
14490+
inferFromTypes(source, (target as SubstitutionType).typeVariable);
14491+
}
1447814492
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
1447914493
// If source and target are references to the same generic type, infer from type arguments
1448014494
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
@@ -14515,7 +14529,8 @@ namespace ts {
1451514529
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
1451614530
}
1451714531
else if (target.flags & TypeFlags.Conditional) {
14518-
inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)]));
14532+
inferFromTypes(source, getTrueTypeFromConditionalType(<ConditionalType>target));
14533+
inferFromTypes(source, getFalseTypeFromConditionalType(<ConditionalType>target));
1451914534
}
1452014535
else if (target.flags & TypeFlags.UnionOrIntersection) {
1452114536
for (const t of (<UnionOrIntersectionType>target).types) {

src/typingsInstaller/nodeTypingsInstaller.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ namespace ts.server.typingsInstaller {
8989
log);
9090
this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]);
9191

92-
// If the NPM path contains spaces and isn't wrapped in quotes, do so.
93-
if (stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) {
94-
this.npmPath = `"${this.npmPath}"`;
95-
}
9692
if (this.log.isEnabled()) {
9793
this.log.writeLine(`Process id: ${process.pid}`);
9894
this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//// [conditionalTypeRelaxingConstraintAssignability.ts]
2+
export type ElChildren =
3+
| ElChildren.Void
4+
| ElChildren.Text;
5+
export namespace ElChildren {
6+
export type Void = undefined;
7+
export type Text = string;
8+
}
9+
10+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
11+
12+
export class Elem<
13+
C extends ElChildren,
14+
> {
15+
constructor(
16+
private children_: Relax<C>,
17+
) {
18+
}
19+
}
20+
21+
new Elem(undefined as ElChildren.Void);
22+
new Elem('' as ElChildren.Text);
23+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
24+
new Elem('' as ElChildren); // error
25+
26+
//// [conditionalTypeRelaxingConstraintAssignability.js]
27+
"use strict";
28+
exports.__esModule = true;
29+
var Elem = /** @class */ (function () {
30+
function Elem(children_) {
31+
this.children_ = children_;
32+
}
33+
return Elem;
34+
}());
35+
exports.Elem = Elem;
36+
new Elem(undefined);
37+
new Elem('');
38+
new Elem(''); // error
39+
new Elem(''); // error
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/conditionalTypeRelaxingConstraintAssignability.ts ===
2+
export type ElChildren =
3+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
4+
5+
| ElChildren.Void
6+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
7+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
8+
9+
| ElChildren.Text;
10+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
11+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
12+
13+
export namespace ElChildren {
14+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
15+
16+
export type Void = undefined;
17+
>Void : Symbol(Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
18+
19+
export type Text = string;
20+
>Text : Symbol(Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
21+
}
22+
23+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
24+
>Relax : Symbol(Relax, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 6, 1))
25+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
26+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
27+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
28+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
29+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
30+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
31+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
32+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
33+
34+
export class Elem<
35+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
36+
37+
C extends ElChildren,
38+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 10, 18))
39+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
40+
41+
> {
42+
constructor(
43+
private children_: Relax<C>,
44+
>children_ : Symbol(Elem.children_, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 13, 14))
45+
>Relax : Symbol(Relax, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 6, 1))
46+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 10, 18))
47+
48+
) {
49+
}
50+
}
51+
52+
new Elem(undefined as ElChildren.Void);
53+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
54+
>undefined : Symbol(undefined)
55+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
56+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
57+
58+
new Elem('' as ElChildren.Text);
59+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
60+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
61+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
62+
63+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
64+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
65+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
66+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
67+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
68+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
69+
70+
new Elem('' as ElChildren); // error
71+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
72+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
73+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
=== tests/cases/compiler/conditionalTypeRelaxingConstraintAssignability.ts ===
2+
export type ElChildren =
3+
>ElChildren : ElChildren
4+
5+
| ElChildren.Void
6+
>ElChildren : any
7+
8+
| ElChildren.Text;
9+
>ElChildren : any
10+
11+
export namespace ElChildren {
12+
export type Void = undefined;
13+
>Void : undefined
14+
15+
export type Text = string;
16+
>Text : string
17+
}
18+
19+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
20+
>Relax : Relax<C>
21+
>ElChildren : any
22+
>ElChildren : any
23+
24+
export class Elem<
25+
>Elem : Elem<C>
26+
27+
C extends ElChildren,
28+
> {
29+
constructor(
30+
private children_: Relax<C>,
31+
>children_ : Relax<C>
32+
33+
) {
34+
}
35+
}
36+
37+
new Elem(undefined as ElChildren.Void);
38+
>new Elem(undefined as ElChildren.Void) : Elem<undefined>
39+
>Elem : typeof Elem
40+
>undefined as ElChildren.Void : undefined
41+
>undefined : undefined
42+
>ElChildren : any
43+
44+
new Elem('' as ElChildren.Text);
45+
>new Elem('' as ElChildren.Text) : Elem<string>
46+
>Elem : typeof Elem
47+
>'' as ElChildren.Text : string
48+
>'' : ""
49+
>ElChildren : any
50+
51+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
52+
>new Elem('' as ElChildren.Void | ElChildren.Text) : Elem<ElChildren>
53+
>Elem : typeof Elem
54+
>'' as ElChildren.Void | ElChildren.Text : ElChildren
55+
>'' : ""
56+
>ElChildren : any
57+
>ElChildren : any
58+
59+
new Elem('' as ElChildren); // error
60+
>new Elem('' as ElChildren) : Elem<ElChildren>
61+
>Elem : typeof Elem
62+
>'' as ElChildren : ElChildren
63+
>'' : ""
64+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
tests/cases/compiler/emptyObjectNotSubtypeOfIndexSignatureContainingObject1.ts(41,3): error TS2322: Type 'Dictionary<string>' is not assignable to type 'Record<string, Bar>'.
2+
Index signatures are incompatible.
3+
Type 'string' is not assignable to type 'Bar'.
4+
5+
6+
==== tests/cases/compiler/emptyObjectNotSubtypeOfIndexSignatureContainingObject1.ts (1 errors) ====
7+
// This should behave the same as emptyObjectNotSubtypeOfIndexSignatureContainingObject2.ts
8+
// Begin types from Lodash.
9+
interface Dictionary<T> {
10+
[index: string]: T;
11+
}
12+
13+
interface NumericDictionary<T> {
14+
[index: number]: T;
15+
}
16+
17+
type ObjectIterator<TObject, TResult> = (
18+
value: TObject[keyof TObject],
19+
key: string,
20+
collection: TObject
21+
) => TResult;
22+
23+
type DictionaryIterator<T, TResult> = ObjectIterator<Dictionary<T>, TResult>;
24+
25+
// In lodash.d.ts this function has many overloads, but this seems to be the problematic one.
26+
function mapValues<T, TResult>(
27+
obj: Dictionary<T> | NumericDictionary<T> | null | undefined,
28+
callback: DictionaryIterator<T, TResult>
29+
): Dictionary<TResult> {
30+
return null as any;
31+
}
32+
// End types from Lodash.
33+
34+
interface Foo {
35+
foo: string;
36+
}
37+
38+
interface Bar {
39+
bar: string;
40+
}
41+
42+
export function fooToBar(
43+
foos: Record<string, Foo>
44+
): Record<string, Bar | null> {
45+
const result = foos == null ? {} : mapValues(foos, f => f.foo);
46+
// This line _should_ fail, because `result` is not the right type.
47+
return result;
48+
~~~~~~~~~~~~~~
49+
!!! error TS2322: Type 'Dictionary<string>' is not assignable to type 'Record<string, Bar>'.
50+
!!! error TS2322: Index signatures are incompatible.
51+
!!! error TS2322: Type 'string' is not assignable to type 'Bar'.
52+
}
53+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//// [emptyObjectNotSubtypeOfIndexSignatureContainingObject1.ts]
2+
// This should behave the same as emptyObjectNotSubtypeOfIndexSignatureContainingObject2.ts
3+
// Begin types from Lodash.
4+
interface Dictionary<T> {
5+
[index: string]: T;
6+
}
7+
8+
interface NumericDictionary<T> {
9+
[index: number]: T;
10+
}
11+
12+
type ObjectIterator<TObject, TResult> = (
13+
value: TObject[keyof TObject],
14+
key: string,
15+
collection: TObject
16+
) => TResult;
17+
18+
type DictionaryIterator<T, TResult> = ObjectIterator<Dictionary<T>, TResult>;
19+
20+
// In lodash.d.ts this function has many overloads, but this seems to be the problematic one.
21+
function mapValues<T, TResult>(
22+
obj: Dictionary<T> | NumericDictionary<T> | null | undefined,
23+
callback: DictionaryIterator<T, TResult>
24+
): Dictionary<TResult> {
25+
return null as any;
26+
}
27+
// End types from Lodash.
28+
29+
interface Foo {
30+
foo: string;
31+
}
32+
33+
interface Bar {
34+
bar: string;
35+
}
36+
37+
export function fooToBar(
38+
foos: Record<string, Foo>
39+
): Record<string, Bar | null> {
40+
const result = foos == null ? {} : mapValues(foos, f => f.foo);
41+
// This line _should_ fail, because `result` is not the right type.
42+
return result;
43+
}
44+
45+
46+
//// [emptyObjectNotSubtypeOfIndexSignatureContainingObject1.js]
47+
"use strict";
48+
exports.__esModule = true;
49+
// In lodash.d.ts this function has many overloads, but this seems to be the problematic one.
50+
function mapValues(obj, callback) {
51+
return null;
52+
}
53+
function fooToBar(foos) {
54+
var result = foos == null ? {} : mapValues(foos, function (f) { return f.foo; });
55+
// This line _should_ fail, because `result` is not the right type.
56+
return result;
57+
}
58+
exports.fooToBar = fooToBar;

0 commit comments

Comments
 (0)