Skip to content

Commit cae1286

Browse files
authored
Merge pull request #16343 from Microsoft/weak-types-for-primitives
Weak type errors for primitives
2 parents eadafd2 + a5b68c0 commit cae1286

10 files changed

+75
-44
lines changed

src/compiler/checker.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -14226,9 +14226,13 @@ namespace ts {
1422614226

1422714227
/**
1422814228
* Check if a property with the given name is known anywhere in the given type. In an object type, a property
14229-
* is considered known if the object type is empty and the check is for assignability, if the object type has
14230-
* index signatures, or if the property is actually declared in the object type. In a union or intersection
14231-
* type, a property is considered known if it is known in any constituent type.
14229+
* is considered known if
14230+
* 1. the object type is empty and the check is for assignability, or
14231+
* 2. if the object type has index signatures, or
14232+
* 3. if the property is actually declared in the object type
14233+
* (this means that 'toString', for example, is not usually a known property).
14234+
* 4. In a union or intersection type,
14235+
* a property is considered known if it is known in any constituent type.
1423214236
* @param targetType a type to search a given name in
1423314237
* @param name a property name to search
1423414238
* @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType
@@ -14238,7 +14242,7 @@ namespace ts {
1423814242
const resolved = resolveStructuredTypeMembers(<ObjectType>targetType);
1423914243
if (resolved.stringIndexInfo ||
1424014244
resolved.numberIndexInfo && isNumericLiteralName(name) ||
14241-
getPropertyOfType(targetType, name) ||
14245+
getPropertyOfObjectType(targetType, name) ||
1424214246
isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
1424314247
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
1424414248
return true;

tests/baselines/reference/generatorTypeCheck63.errors.txt

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
2-
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
3-
Type 'State | 1' is not assignable to type 'State'.
4-
Type '1' is not assignable to type 'State'.
1+
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
2+
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
3+
Type 'State | 1' is not assignable to type 'StrategicState'.
4+
Type '1' has no properties in common with type 'StrategicState'.
55
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(29,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
66
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(32,42): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
77
Type argument candidate 'State' is not a valid type argument because it is not a supertype of candidate '1'.
8-
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
8+
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,62): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
9+
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
910

1011

1112
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts (4 errors) ====
@@ -33,11 +34,11 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): err
3334
}
3435

3536
export const Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
36-
~~~~~~~
37-
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
38-
!!! error TS2322: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
39-
!!! error TS2322: Type 'State | 1' is not assignable to type 'State'.
40-
!!! error TS2322: Type '1' is not assignable to type 'State'.
37+
~~~~~~~~
38+
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
39+
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
40+
!!! error TS2345: Type 'State | 1' is not assignable to type 'StrategicState'.
41+
!!! error TS2345: Type '1' has no properties in common with type 'StrategicState'.
4142
yield 1;
4243
return state;
4344
});
@@ -55,8 +56,9 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): err
5556
});
5657

5758
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
58-
~~~~~~~~
59-
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
59+
~~~~~~~~
60+
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
61+
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
6062
yield state;
6163
return 1;
6264
});

tests/baselines/reference/objectLiteralFunctionArgContextualTyping2.errors.txt

+12-12
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(9,4): error TS
44
Property 'doStuff' is missing in type '{ value: string; }'.
55
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(10,17): error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
66
Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
7-
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,4): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
8-
Property 'value' is missing in type '{ toString: (s: any) => any; }'.
9-
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,4): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
10-
Property 'value' is missing in type '{ toString: (s: string) => string; }'.
11-
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,4): error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
12-
Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
7+
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,6): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
8+
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
9+
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,6): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
10+
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
11+
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,17): error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
12+
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
1313

1414

1515
==== tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts (6 errors) ====
@@ -33,14 +33,14 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,4): error T
3333
!!! error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
3434
!!! error TS2345: Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
3535
f2({ toString: (s) => s })
36-
~~~~~~~~~~~~~~~~~~~~~~
36+
~~~~~~~~~~~~~~~~~~
3737
!!! error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
38-
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: any) => any; }'.
38+
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
3939
f2({ toString: (s: string) => s })
40-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40+
~~~~~~~~~~~~~~~~~~~~~~~~~~
4141
!!! error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
42-
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: string) => string; }'.
42+
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
4343
f2({ value: '', toString: (s) => s.uhhh })
44-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44+
~~~~~~~~~~~~~~~~~~~~~~~
4545
!!! error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
46-
!!! error TS2345: Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
46+
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.

tests/baselines/reference/tsxSpreadAttributesResolution1.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ class Poisoned extends React.Component<{}, {}> {
77
}
88
}
99

10-
const obj: Object = {};
10+
const obj = {};
1111

1212
// OK
1313
let p = <Poisoned {...obj} />;
14-
let y = <Poisoned />;
14+
let y = <Poisoned />;
15+
1516

1617
//// [file.jsx]
1718
"use strict";

tests/baselines/reference/tsxSpreadAttributesResolution1.symbols

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ class Poisoned extends React.Component<{}, {}> {
1717
}
1818
}
1919

20-
const obj: Object = {};
20+
const obj = {};
2121
>obj : Symbol(obj, Decl(file.tsx, 8, 5))
22-
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
2322

2423
// OK
2524
let p = <Poisoned {...obj} />;

tests/baselines/reference/tsxSpreadAttributesResolution1.types

+3-4
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@ class Poisoned extends React.Component<{}, {}> {
1818
}
1919
}
2020

21-
const obj: Object = {};
22-
>obj : Object
23-
>Object : Object
21+
const obj = {};
22+
>obj : {}
2423
>{} : {}
2524

2625
// OK
2726
let p = <Poisoned {...obj} />;
2827
>p : JSX.Element
2928
><Poisoned {...obj} /> : JSX.Element
3029
>Poisoned : typeof Poisoned
31-
>obj : Object
30+
>obj : {}
3231

3332
let y = <Poisoned />;
3433
>y : JSX.Element

tests/baselines/reference/weakType.errors.txt

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
tests/cases/compiler/weakType.ts(31,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
2-
tests/cases/compiler/weakType.ts(56,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
1+
tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '12' has no properties in common with type 'Settings'.
2+
tests/cases/compiler/weakType.ts(17,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
3+
tests/cases/compiler/weakType.ts(18,13): error TS2559: Type 'false' has no properties in common with type 'Settings'.
4+
tests/cases/compiler/weakType.ts(35,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
5+
tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
36
Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
47
Types of property 'properties' are incompatible.
58
Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
69

710

8-
==== tests/cases/compiler/weakType.ts (2 errors) ====
11+
==== tests/cases/compiler/weakType.ts (5 errors) ====
912
interface Settings {
1013
timeout?: number;
1114
onError?(): void;
@@ -16,10 +19,20 @@ tests/cases/compiler/weakType.ts(56,5): error TS2322: Type '{ properties: { wron
1619
}
1720

1821
function doSomething(settings: Settings) { /* ... */ }
19-
2022
// forgot to call `getDefaultSettings`
2123
// but it is not caught because we don't check for call signatures
2224
doSomething(getDefaultSettings);
25+
// same for arrow expressions:
26+
doSomething(() => { });
27+
doSomething(12);
28+
~~
29+
!!! error TS2559: Type '12' has no properties in common with type 'Settings'.
30+
doSomething('completely wrong');
31+
~~~~~~~~~~~~~~~~~~
32+
!!! error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
33+
doSomething(false);
34+
~~~~~
35+
!!! error TS2559: Type 'false' has no properties in common with type 'Settings'.
2336

2437
// this is an oddly popular way of defining settings
2538
// this example is from services/textChanges.ts

tests/baselines/reference/weakType.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ function getDefaultSettings() {
99
}
1010

1111
function doSomething(settings: Settings) { /* ... */ }
12-
1312
// forgot to call `getDefaultSettings`
1413
// but it is not caught because we don't check for call signatures
1514
doSomething(getDefaultSettings);
15+
// same for arrow expressions:
16+
doSomething(() => { });
17+
doSomething(12);
18+
doSomething('completely wrong');
19+
doSomething(false);
1620

1721
// this is an oddly popular way of defining settings
1822
// this example is from services/textChanges.ts
@@ -65,6 +69,11 @@ function doSomething(settings) { }
6569
// forgot to call `getDefaultSettings`
6670
// but it is not caught because we don't check for call signatures
6771
doSomething(getDefaultSettings);
72+
// same for arrow expressions:
73+
doSomething(function () { });
74+
doSomething(12);
75+
doSomething('completely wrong');
76+
doSomething(false);
6877
function del(options, error) {
6978
if (options === void 0) { options = {}; }
7079
if (error === void 0) { error = {}; }

tests/cases/compiler/weakType.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ function getDefaultSettings() {
88
}
99

1010
function doSomething(settings: Settings) { /* ... */ }
11-
1211
// forgot to call `getDefaultSettings`
1312
// but it is not caught because we don't check for call signatures
1413
doSomething(getDefaultSettings);
14+
// same for arrow expressions:
15+
doSomething(() => { });
16+
doSomething(12);
17+
doSomething('completely wrong');
18+
doSomething(false);
1519

1620
// this is an oddly popular way of defining settings
1721
// this example is from services/textChanges.ts

tests/cases/conformance/jsx/tsxSpreadAttributesResolution1.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class Poisoned extends React.Component<{}, {}> {
1111
}
1212
}
1313

14-
const obj: Object = {};
14+
const obj = {};
1515

1616
// OK
1717
let p = <Poisoned {...obj} />;
18-
let y = <Poisoned />;
18+
let y = <Poisoned />;

0 commit comments

Comments
 (0)