Skip to content

Weak type errors for primitives #16343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14214,9 +14214,13 @@ namespace ts {

/**
* Check if a property with the given name is known anywhere in the given type. In an object type, a property
* is considered known if the object type is empty and the check is for assignability, if the object type has
* index signatures, or if the property is actually declared in the object type. In a union or intersection
* type, a property is considered known if it is known in any constituent type.
* is considered known if
* 1. the object type is empty and the check is for assignability, or
* 2. if the object type has index signatures, or
* 3. if the property is actually declared in the object type
* (this means that 'toString', for example, is not usually a known property).
* 4. In a union or intersection type,
* a property is considered known if it is known in any constituent type.
* @param targetType a type to search a given name in
* @param name a property name to search
* @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType
Expand All @@ -14226,7 +14230,7 @@ namespace ts {
const resolved = resolveStructuredTypeMembers(<ObjectType>targetType);
if (resolved.stringIndexInfo ||
resolved.numberIndexInfo && isNumericLiteralName(name) ||
getPropertyOfType(targetType, name) ||
getPropertyOfObjectType(targetType, name) ||
isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
return true;
Expand Down
26 changes: 14 additions & 12 deletions tests/baselines/reference/generatorTypeCheck63.errors.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
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>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
Type 'State | 1' is not assignable to type 'State'.
Type '1' is not assignable to type 'State'.
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>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
Type 'State | 1' is not assignable to type 'StrategicState'.
Type '1' has no properties in common with type 'StrategicState'.
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.
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.
Type argument candidate 'State' is not a valid type argument because it is not a supertype of candidate '1'.
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>'.
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>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.


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

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

export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
~~~~~~~~
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
yield state;
return 1;
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(9,4): error TS
Property 'doStuff' is missing in type '{ value: string; }'.
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(10,17): error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,4): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
Property 'value' is missing in type '{ toString: (s: any) => any; }'.
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,4): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
Property 'value' is missing in type '{ toString: (s: string) => string; }'.
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'.
Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,6): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,6): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
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'.
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.


==== tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts (6 errors) ====
Expand All @@ -33,14 +33,14 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,4): error T
!!! error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
!!! error TS2345: Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
f2({ toString: (s) => s })
~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: any) => any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
f2({ toString: (s: string) => s })
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: string) => string; }'.
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
f2({ value: '', toString: (s) => s.uhhh })
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
!!! error TS2345: Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
5 changes: 3 additions & 2 deletions tests/baselines/reference/tsxSpreadAttributesResolution1.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ class Poisoned extends React.Component<{}, {}> {
}
}

const obj: Object = {};
const obj = {};

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


//// [file.jsx]
"use strict";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ class Poisoned extends React.Component<{}, {}> {
}
}

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

// OK
let p = <Poisoned {...obj} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@ class Poisoned extends React.Component<{}, {}> {
}
}

const obj: Object = {};
>obj : Object
>Object : Object
const obj = {};
>obj : {}
>{} : {}

// OK
let p = <Poisoned {...obj} />;
>p : JSX.Element
><Poisoned {...obj} /> : JSX.Element
>Poisoned : typeof Poisoned
>obj : Object
>obj : {}

let y = <Poisoned />;
>y : JSX.Element
Expand Down
21 changes: 17 additions & 4 deletions tests/baselines/reference/weakType.errors.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
tests/cases/compiler/weakType.ts(31,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
tests/cases/compiler/weakType.ts(56,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '12' has no properties in common with type 'Settings'.
tests/cases/compiler/weakType.ts(17,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
tests/cases/compiler/weakType.ts(18,13): error TS2559: Type 'false' has no properties in common with type 'Settings'.
tests/cases/compiler/weakType.ts(35,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
Types of property 'properties' are incompatible.
Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.


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

function doSomething(settings: Settings) { /* ... */ }

// forgot to call `getDefaultSettings`
// but it is not caught because we don't check for call signatures
doSomething(getDefaultSettings);
// same for arrow expressions:
doSomething(() => { });
doSomething(12);
~~
!!! error TS2559: Type '12' has no properties in common with type 'Settings'.
doSomething('completely wrong');
~~~~~~~~~~~~~~~~~~
!!! error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
doSomething(false);
~~~~~
!!! error TS2559: Type 'false' has no properties in common with type 'Settings'.

// this is an oddly popular way of defining settings
// this example is from services/textChanges.ts
Expand Down
11 changes: 10 additions & 1 deletion tests/baselines/reference/weakType.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ function getDefaultSettings() {
}

function doSomething(settings: Settings) { /* ... */ }

// forgot to call `getDefaultSettings`
// but it is not caught because we don't check for call signatures
doSomething(getDefaultSettings);
// same for arrow expressions:
doSomething(() => { });
doSomething(12);
doSomething('completely wrong');
doSomething(false);

// this is an oddly popular way of defining settings
// this example is from services/textChanges.ts
Expand Down Expand Up @@ -65,6 +69,11 @@ function doSomething(settings) { }
// forgot to call `getDefaultSettings`
// but it is not caught because we don't check for call signatures
doSomething(getDefaultSettings);
// same for arrow expressions:
doSomething(function () { });
doSomething(12);
doSomething('completely wrong');
doSomething(false);
function del(options, error) {
if (options === void 0) { options = {}; }
if (error === void 0) { error = {}; }
Expand Down
6 changes: 5 additions & 1 deletion tests/cases/compiler/weakType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ function getDefaultSettings() {
}

function doSomething(settings: Settings) { /* ... */ }

// forgot to call `getDefaultSettings`
// but it is not caught because we don't check for call signatures
doSomething(getDefaultSettings);
// same for arrow expressions:
doSomething(() => { });
doSomething(12);
doSomething('completely wrong');
doSomething(false);

// this is an oddly popular way of defining settings
// this example is from services/textChanges.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Poisoned extends React.Component<{}, {}> {
}
}

const obj: Object = {};
const obj = {};

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