From 37d539d92c114ebe50e0d74ae0e4b6c7b170c5d6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 12:19:14 -0800 Subject: [PATCH 1/6] Treat intersections of only objects as a single object in relations --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 18d32322297f0..bb3083144fe3b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15363,7 +15363,9 @@ namespace ts { // // - 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 (!isNonGenericObjectType(target) || !every((source).types, isNonGenericObjectType)) { + 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)) { From 583ca838db4b887e9b1365c371ea8e4c897c57f5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 14:08:24 -0800 Subject: [PATCH 2/6] Exclude intersections containing non-inferrable types --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bb3083144fe3b..fe5d10949e7ff 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15363,7 +15363,7 @@ namespace ts { // // - For a primitive type or type parameter (such as 'number = A & B') there is no point in // breaking the intersection apart. - if (!isNonGenericObjectType(target) || !every((source).types, isNonGenericObjectType)) { + if (!isNonGenericObjectType(target) || !every((source).types, t => isNonGenericObjectType(t) && !(getObjectFlags(t) & ObjectFlags.NonInferrableType))) { result = someTypeRelatedToType(source, target, /*reportErrors*/ false, IntersectionState.Source); } } From 1e114d2c5466c71067cb755ae8eb9d936e8b9add Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 14:09:05 -0800 Subject: [PATCH 3/6] Accept new baselines --- ...ormalizedIntersectionTooComplex.errors.txt | 6 +- .../propTypeValidatorInference.errors.txt | 118 ++++++++++++++++++ 2 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/propTypeValidatorInference.errors.txt diff --git a/tests/baselines/reference/normalizedIntersectionTooComplex.errors.txt b/tests/baselines/reference/normalizedIntersectionTooComplex.errors.txt index 64e7d7f00c510..4e214eff50715 100644 --- a/tests/baselines/reference/normalizedIntersectionTooComplex.errors.txt +++ b/tests/baselines/reference/normalizedIntersectionTooComplex.errors.txt @@ -1,5 +1,5 @@ +tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,14): error TS2590: Expression produces a union type that is too complex to represent. tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,40): error TS7006: Parameter 'x' implicitly has an 'any' type. -tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,40): error TS2590: Expression produces a union type that is too complex to represent. ==== tests/cases/compiler/normalizedIntersectionTooComplex.ts (2 errors) ==== @@ -39,8 +39,8 @@ tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,40): error TS2590: E declare var all: keyof Big; const ctor = getCtor(all); const comp = ctor({ common: "ok", ref: x => console.log(x) }); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. ~ !!! error TS7006: Parameter 'x' implicitly has an 'any' type. - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2590: Expression produces a union type that is too complex to represent. \ No newline at end of file diff --git a/tests/baselines/reference/propTypeValidatorInference.errors.txt b/tests/baselines/reference/propTypeValidatorInference.errors.txt new file mode 100644 index 0000000000000..277ac5ce532ea --- /dev/null +++ b/tests/baselines/reference/propTypeValidatorInference.errors.txt @@ -0,0 +1,118 @@ +tests/cases/compiler/file.ts(35,5): error TS2322: Type 'Validator; bar: Requireable; baz: Requireable; }>>' is not assignable to type 'Validator<{ foo: string; bar?: boolean | undefined; baz?: any; }>'. + Type 'InferProps<{ foo: Validator; bar: Requireable; baz: Requireable; }>' is not assignable to type '{ foo: string; bar?: boolean | undefined; baz?: any; }'. + Types of property 'bar' are incompatible. + Type 'boolean | null | undefined' is not assignable to type 'boolean | undefined'. + Type 'null' is not assignable to type 'boolean | undefined'. +tests/cases/compiler/file.ts(36,5): error TS2322: Type 'Validator; bar: Validator; }>>' is not assignable to type 'Validator'. + Type 'string | boolean | InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. + Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. + Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type '{ foo?: string | undefined; bar: number; }'. + Types of property 'foo' are incompatible. + Type 'string | null | undefined' is not assignable to type 'string | undefined'. + Type 'null' is not assignable to type 'string | undefined'. + + +==== tests/cases/compiler/node_modules/prop-types/index.d.ts (0 errors) ==== + export const nominalTypeHack: unique symbol; + + export type IsOptional = undefined | null extends T ? true : undefined extends T ? true : null extends T ? true : false; + + export type RequiredKeys = { [K in keyof V]-?: Exclude extends Validator ? IsOptional extends true ? never : K : never }[keyof V]; + export type OptionalKeys = Exclude>; + export type InferPropsInner = { [K in keyof V]-?: InferType; }; + + export interface Validator { + (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; + [nominalTypeHack]?: T; + } + + export interface Requireable extends Validator { + isRequired: Validator>; + } + + export type ValidationMap = { [K in keyof T]?: Validator }; + + export type InferType = V extends Validator ? T : any; + export type InferProps = + & InferPropsInner>> + & Partial>>>; + + export const any: Requireable; + export const array: Requireable; + export const bool: Requireable; + export const string: Requireable; + export const number: Requireable; + export function shape

>(type: P): Requireable>; + export function oneOfType>(types: T[]): Requireable>>; + + +==== tests/cases/compiler/file.ts (2 errors) ==== + import * as PropTypes from "prop-types"; + interface Props { + any?: any; + array: string[]; + bool: boolean; + shape: { + foo: string; + bar?: boolean; + baz?: any + }; + oneOfType: string | boolean | { + foo?: string; + bar: number; + }; + } + + type PropTypesMap = PropTypes.ValidationMap; + + const innerProps = { + foo: PropTypes.string.isRequired, + bar: PropTypes.bool, + baz: PropTypes.any + }; + + const arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({ + foo: PropTypes.string, + bar: PropTypes.number.isRequired + })]; + + // TS checking + const propTypes: PropTypesMap = { + any: PropTypes.any, + array: PropTypes.array.isRequired, + bool: PropTypes.bool.isRequired, + shape: PropTypes.shape(innerProps).isRequired, + ~~~~~ +!!! error TS2322: Type 'Validator; bar: Requireable; baz: Requireable; }>>' is not assignable to type 'Validator<{ foo: string; bar?: boolean | undefined; baz?: any; }>'. +!!! error TS2322: Type 'InferProps<{ foo: Validator; bar: Requireable; baz: Requireable; }>' is not assignable to type '{ foo: string; bar?: boolean | undefined; baz?: any; }'. +!!! error TS2322: Types of property 'bar' are incompatible. +!!! error TS2322: Type 'boolean | null | undefined' is not assignable to type 'boolean | undefined'. +!!! error TS2322: Type 'null' is not assignable to type 'boolean | undefined'. +!!! related TS6500 tests/cases/compiler/file.ts:6:5: The expected type comes from property 'shape' which is declared here on type 'ValidationMap' + oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, + ~~~~~~~~~ +!!! error TS2322: Type 'Validator; bar: Validator; }>>' is not assignable to type 'Validator'. +!!! error TS2322: Type 'string | boolean | InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. +!!! error TS2322: Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. +!!! error TS2322: Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type '{ foo?: string | undefined; bar: number; }'. +!!! error TS2322: Types of property 'foo' are incompatible. +!!! error TS2322: Type 'string | null | undefined' is not assignable to type 'string | undefined'. +!!! error TS2322: Type 'null' is not assignable to type 'string | undefined'. +!!! related TS6500 tests/cases/compiler/file.ts:11:5: The expected type comes from property 'oneOfType' which is declared here on type 'ValidationMap' + }; + + // JS checking + const propTypesWithoutAnnotation = { + any: PropTypes.any, + array: PropTypes.array.isRequired, + bool: PropTypes.bool.isRequired, + shape: PropTypes.shape(innerProps).isRequired, + oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, + }; + + type ExtractedProps = PropTypes.InferProps; + + type ExtractedPropsWithoutAnnotation = PropTypes.InferProps; + + type ExtractPropsMatch = ExtractedProps extends ExtractedPropsWithoutAnnotation ? true : false; + const x: true = (null as any as ExtractPropsMatch); \ No newline at end of file From 0a207cc318a2d18aecdf5ba8decf76c2af39bfac Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 14:10:32 -0800 Subject: [PATCH 4/6] Update test --- tests/cases/compiler/propTypeValidatorInference.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/compiler/propTypeValidatorInference.ts b/tests/cases/compiler/propTypeValidatorInference.ts index 54030ab91a916..9f6120a5d67ac 100644 --- a/tests/cases/compiler/propTypeValidatorInference.ts +++ b/tests/cases/compiler/propTypeValidatorInference.ts @@ -13,7 +13,7 @@ export interface Validator { [nominalTypeHack]?: T; } -export interface Requireable extends Validator { +export interface Requireable extends Validator { isRequired: Validator>; } From adeb53237bd61c794f5738f639135950a198d7a6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 14:10:40 -0800 Subject: [PATCH 5/6] Accept new baselines --- .../propTypeValidatorInference.errors.txt | 118 ------------------ .../reference/propTypeValidatorInference.js | 2 +- .../propTypeValidatorInference.symbols | 44 +++---- .../propTypeValidatorInference.types | 4 +- 4 files changed, 24 insertions(+), 144 deletions(-) delete mode 100644 tests/baselines/reference/propTypeValidatorInference.errors.txt diff --git a/tests/baselines/reference/propTypeValidatorInference.errors.txt b/tests/baselines/reference/propTypeValidatorInference.errors.txt deleted file mode 100644 index 277ac5ce532ea..0000000000000 --- a/tests/baselines/reference/propTypeValidatorInference.errors.txt +++ /dev/null @@ -1,118 +0,0 @@ -tests/cases/compiler/file.ts(35,5): error TS2322: Type 'Validator; bar: Requireable; baz: Requireable; }>>' is not assignable to type 'Validator<{ foo: string; bar?: boolean | undefined; baz?: any; }>'. - Type 'InferProps<{ foo: Validator; bar: Requireable; baz: Requireable; }>' is not assignable to type '{ foo: string; bar?: boolean | undefined; baz?: any; }'. - Types of property 'bar' are incompatible. - Type 'boolean | null | undefined' is not assignable to type 'boolean | undefined'. - Type 'null' is not assignable to type 'boolean | undefined'. -tests/cases/compiler/file.ts(36,5): error TS2322: Type 'Validator; bar: Validator; }>>' is not assignable to type 'Validator'. - Type 'string | boolean | InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. - Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. - Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type '{ foo?: string | undefined; bar: number; }'. - Types of property 'foo' are incompatible. - Type 'string | null | undefined' is not assignable to type 'string | undefined'. - Type 'null' is not assignable to type 'string | undefined'. - - -==== tests/cases/compiler/node_modules/prop-types/index.d.ts (0 errors) ==== - export const nominalTypeHack: unique symbol; - - export type IsOptional = undefined | null extends T ? true : undefined extends T ? true : null extends T ? true : false; - - export type RequiredKeys = { [K in keyof V]-?: Exclude extends Validator ? IsOptional extends true ? never : K : never }[keyof V]; - export type OptionalKeys = Exclude>; - export type InferPropsInner = { [K in keyof V]-?: InferType; }; - - export interface Validator { - (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; - [nominalTypeHack]?: T; - } - - export interface Requireable extends Validator { - isRequired: Validator>; - } - - export type ValidationMap = { [K in keyof T]?: Validator }; - - export type InferType = V extends Validator ? T : any; - export type InferProps = - & InferPropsInner>> - & Partial>>>; - - export const any: Requireable; - export const array: Requireable; - export const bool: Requireable; - export const string: Requireable; - export const number: Requireable; - export function shape

>(type: P): Requireable>; - export function oneOfType>(types: T[]): Requireable>>; - - -==== tests/cases/compiler/file.ts (2 errors) ==== - import * as PropTypes from "prop-types"; - interface Props { - any?: any; - array: string[]; - bool: boolean; - shape: { - foo: string; - bar?: boolean; - baz?: any - }; - oneOfType: string | boolean | { - foo?: string; - bar: number; - }; - } - - type PropTypesMap = PropTypes.ValidationMap; - - const innerProps = { - foo: PropTypes.string.isRequired, - bar: PropTypes.bool, - baz: PropTypes.any - }; - - const arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({ - foo: PropTypes.string, - bar: PropTypes.number.isRequired - })]; - - // TS checking - const propTypes: PropTypesMap = { - any: PropTypes.any, - array: PropTypes.array.isRequired, - bool: PropTypes.bool.isRequired, - shape: PropTypes.shape(innerProps).isRequired, - ~~~~~ -!!! error TS2322: Type 'Validator; bar: Requireable; baz: Requireable; }>>' is not assignable to type 'Validator<{ foo: string; bar?: boolean | undefined; baz?: any; }>'. -!!! error TS2322: Type 'InferProps<{ foo: Validator; bar: Requireable; baz: Requireable; }>' is not assignable to type '{ foo: string; bar?: boolean | undefined; baz?: any; }'. -!!! error TS2322: Types of property 'bar' are incompatible. -!!! error TS2322: Type 'boolean | null | undefined' is not assignable to type 'boolean | undefined'. -!!! error TS2322: Type 'null' is not assignable to type 'boolean | undefined'. -!!! related TS6500 tests/cases/compiler/file.ts:6:5: The expected type comes from property 'shape' which is declared here on type 'ValidationMap' - oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, - ~~~~~~~~~ -!!! error TS2322: Type 'Validator; bar: Validator; }>>' is not assignable to type 'Validator'. -!!! error TS2322: Type 'string | boolean | InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. -!!! error TS2322: Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type 'string | boolean | { foo?: string | undefined; bar: number; }'. -!!! error TS2322: Type 'InferProps<{ foo: Requireable; bar: Validator; }>' is not assignable to type '{ foo?: string | undefined; bar: number; }'. -!!! error TS2322: Types of property 'foo' are incompatible. -!!! error TS2322: Type 'string | null | undefined' is not assignable to type 'string | undefined'. -!!! error TS2322: Type 'null' is not assignable to type 'string | undefined'. -!!! related TS6500 tests/cases/compiler/file.ts:11:5: The expected type comes from property 'oneOfType' which is declared here on type 'ValidationMap' - }; - - // JS checking - const propTypesWithoutAnnotation = { - any: PropTypes.any, - array: PropTypes.array.isRequired, - bool: PropTypes.bool.isRequired, - shape: PropTypes.shape(innerProps).isRequired, - oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, - }; - - type ExtractedProps = PropTypes.InferProps; - - type ExtractedPropsWithoutAnnotation = PropTypes.InferProps; - - type ExtractPropsMatch = ExtractedProps extends ExtractedPropsWithoutAnnotation ? true : false; - const x: true = (null as any as ExtractPropsMatch); \ No newline at end of file diff --git a/tests/baselines/reference/propTypeValidatorInference.js b/tests/baselines/reference/propTypeValidatorInference.js index 3a6fa04fbe183..de1b7e99e1fc2 100644 --- a/tests/baselines/reference/propTypeValidatorInference.js +++ b/tests/baselines/reference/propTypeValidatorInference.js @@ -14,7 +14,7 @@ export interface Validator { [nominalTypeHack]?: T; } -export interface Requireable extends Validator { +export interface Requireable extends Validator { isRequired: Validator>; } diff --git a/tests/baselines/reference/propTypeValidatorInference.symbols b/tests/baselines/reference/propTypeValidatorInference.symbols index 32a4a3c1abf3b..320c2c46bcd25 100644 --- a/tests/baselines/reference/propTypeValidatorInference.symbols +++ b/tests/baselines/reference/propTypeValidatorInference.symbols @@ -59,14 +59,14 @@ export interface Validator { >T : Symbol(T, Decl(index.d.ts, 8, 27)) } -export interface Requireable extends Validator { +export interface Requireable extends Validator { >Requireable : Symbol(Requireable, Decl(index.d.ts, 11, 1)) >T : Symbol(T, Decl(index.d.ts, 13, 29)) >Validator : Symbol(Validator, Decl(index.d.ts, 6, 72)) >T : Symbol(T, Decl(index.d.ts, 13, 29)) isRequired: Validator>; ->isRequired : Symbol(Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(Requireable.isRequired, Decl(index.d.ts, 13, 54)) >Validator : Symbol(Validator, Decl(index.d.ts, 6, 72)) >NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) >T : Symbol(T, Decl(index.d.ts, 13, 29)) @@ -202,11 +202,11 @@ const innerProps = { foo: PropTypes.string.isRequired, >foo : Symbol(foo, Decl(file.ts, 18, 20)) ->PropTypes.string.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.string.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.string : Symbol(PropTypes.string, Decl(index.d.ts, 27, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >string : Symbol(PropTypes.string, Decl(index.d.ts, 27, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) bar: PropTypes.bool, >bar : Symbol(bar, Decl(file.ts, 19, 37)) @@ -242,11 +242,11 @@ const arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({ bar: PropTypes.number.isRequired >bar : Symbol(bar, Decl(file.ts, 25, 26)) ->PropTypes.number.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.number.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.number : Symbol(PropTypes.number, Decl(index.d.ts, 28, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >number : Symbol(PropTypes.number, Decl(index.d.ts, 28, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) })]; @@ -263,37 +263,37 @@ const propTypes: PropTypesMap = { array: PropTypes.array.isRequired, >array : Symbol(array, Decl(file.ts, 31, 23)) ->PropTypes.array.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.array.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.array : Symbol(PropTypes.array, Decl(index.d.ts, 25, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >array : Symbol(PropTypes.array, Decl(index.d.ts, 25, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) bool: PropTypes.bool.isRequired, >bool : Symbol(bool, Decl(file.ts, 32, 38)) ->PropTypes.bool.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.bool.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.bool : Symbol(PropTypes.bool, Decl(index.d.ts, 26, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >bool : Symbol(PropTypes.bool, Decl(index.d.ts, 26, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) shape: PropTypes.shape(innerProps).isRequired, >shape : Symbol(shape, Decl(file.ts, 33, 36)) ->PropTypes.shape(innerProps).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.shape(innerProps).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.shape : Symbol(PropTypes.shape, Decl(index.d.ts, 28, 41)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >shape : Symbol(PropTypes.shape, Decl(index.d.ts, 28, 41)) >innerProps : Symbol(innerProps, Decl(file.ts, 18, 5)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, >oneOfType : Symbol(oneOfType, Decl(file.ts, 34, 50)) ->PropTypes.oneOfType(arrayOfTypes).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.oneOfType(arrayOfTypes).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.oneOfType : Symbol(PropTypes.oneOfType, Decl(index.d.ts, 29, 89)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >oneOfType : Symbol(PropTypes.oneOfType, Decl(index.d.ts, 29, 89)) >arrayOfTypes : Symbol(arrayOfTypes, Decl(file.ts, 24, 5)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) }; @@ -309,37 +309,37 @@ const propTypesWithoutAnnotation = { array: PropTypes.array.isRequired, >array : Symbol(array, Decl(file.ts, 40, 23)) ->PropTypes.array.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.array.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.array : Symbol(PropTypes.array, Decl(index.d.ts, 25, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >array : Symbol(PropTypes.array, Decl(index.d.ts, 25, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) bool: PropTypes.bool.isRequired, >bool : Symbol(bool, Decl(file.ts, 41, 38)) ->PropTypes.bool.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.bool.isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.bool : Symbol(PropTypes.bool, Decl(index.d.ts, 26, 12)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >bool : Symbol(PropTypes.bool, Decl(index.d.ts, 26, 12)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) shape: PropTypes.shape(innerProps).isRequired, >shape : Symbol(shape, Decl(file.ts, 42, 36)) ->PropTypes.shape(innerProps).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.shape(innerProps).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.shape : Symbol(PropTypes.shape, Decl(index.d.ts, 28, 41)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >shape : Symbol(PropTypes.shape, Decl(index.d.ts, 28, 41)) >innerProps : Symbol(innerProps, Decl(file.ts, 18, 5)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired, >oneOfType : Symbol(oneOfType, Decl(file.ts, 43, 50)) ->PropTypes.oneOfType(arrayOfTypes).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>PropTypes.oneOfType(arrayOfTypes).isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) >PropTypes.oneOfType : Symbol(PropTypes.oneOfType, Decl(index.d.ts, 29, 89)) >PropTypes : Symbol(PropTypes, Decl(file.ts, 0, 6)) >oneOfType : Symbol(PropTypes.oneOfType, Decl(index.d.ts, 29, 89)) >arrayOfTypes : Symbol(arrayOfTypes, Decl(file.ts, 24, 5)) ->isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 73)) +>isRequired : Symbol(PropTypes.Requireable.isRequired, Decl(index.d.ts, 13, 54)) }; diff --git a/tests/baselines/reference/propTypeValidatorInference.types b/tests/baselines/reference/propTypeValidatorInference.types index eb292dac5c486..5276e7837fbdd 100644 --- a/tests/baselines/reference/propTypeValidatorInference.types +++ b/tests/baselines/reference/propTypeValidatorInference.types @@ -35,9 +35,7 @@ export interface Validator { >nominalTypeHack : unique symbol } -export interface Requireable extends Validator { ->null : null - +export interface Requireable extends Validator { isRequired: Validator>; >isRequired : Validator> } From f902f8ac6cfcb0df41166109d83f26e0678092ac Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 Mar 2020 14:24:43 -0800 Subject: [PATCH 6/6] Add tests --- ...ersectionsAndOptionalProperties.errors.txt | 49 ++++++++++++++ .../intersectionsAndOptionalProperties.js | 33 ++++++++++ ...intersectionsAndOptionalProperties.symbols | 64 ++++++++++++++++++ .../intersectionsAndOptionalProperties.types | 65 +++++++++++++++++++ .../intersectionsAndOptionalProperties.ts | 23 +++++++ 5 files changed, 234 insertions(+) create mode 100644 tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt create mode 100644 tests/baselines/reference/intersectionsAndOptionalProperties.js create mode 100644 tests/baselines/reference/intersectionsAndOptionalProperties.symbols create mode 100644 tests/baselines/reference/intersectionsAndOptionalProperties.types create mode 100644 tests/cases/compiler/intersectionsAndOptionalProperties.ts diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt b/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt new file mode 100644 index 0000000000000..bcd0a6f841d88 --- /dev/null +++ b/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt @@ -0,0 +1,49 @@ +tests/cases/compiler/intersectionsAndOptionalProperties.ts(5,1): error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'. + Types of property 'a' are incompatible. + Type 'null' is not assignable to type 'number | undefined'. +tests/cases/compiler/intersectionsAndOptionalProperties.ts(6,1): error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'. + Types of property 'a' are incompatible. + Type 'null' is not assignable to type 'number | undefined'. +tests/cases/compiler/intersectionsAndOptionalProperties.ts(19,5): error TS2322: Type 'From' is not assignable to type 'To'. + Types of property 'field' are incompatible. + Type 'null' is not assignable to type 'number | undefined'. +tests/cases/compiler/intersectionsAndOptionalProperties.ts(20,5): error TS2322: Type 'null' is not assignable to type 'number | undefined'. + + +==== tests/cases/compiler/intersectionsAndOptionalProperties.ts (4 errors) ==== + declare let x: { a?: number, b: string }; + declare let y: { a: null, b: string }; + declare let z: { a: null } & { b: string }; + + x = y; // Error + ~ +!!! error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'. + x = z; // Error + ~ +!!! error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'. + + // Repro from #36604 + + interface To { + field?: number; + anotherField: string; + } + + type From = { field: null } & Omit; + + function foo(v: From) { + let x: To; + x = v; // Error + ~ +!!! error TS2322: Type 'From' is not assignable to type 'To'. +!!! error TS2322: Types of property 'field' are incompatible. +!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'. + x.field = v.field; // Error + ~~~~~~~ +!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.js b/tests/baselines/reference/intersectionsAndOptionalProperties.js new file mode 100644 index 0000000000000..b2f13a9f67955 --- /dev/null +++ b/tests/baselines/reference/intersectionsAndOptionalProperties.js @@ -0,0 +1,33 @@ +//// [intersectionsAndOptionalProperties.ts] +declare let x: { a?: number, b: string }; +declare let y: { a: null, b: string }; +declare let z: { a: null } & { b: string }; + +x = y; // Error +x = z; // Error + +// Repro from #36604 + +interface To { + field?: number; + anotherField: string; +} + +type From = { field: null } & Omit; + +function foo(v: From) { + let x: To; + x = v; // Error + x.field = v.field; // Error +} + + +//// [intersectionsAndOptionalProperties.js] +"use strict"; +x = y; // Error +x = z; // Error +function foo(v) { + var x; + x = v; // Error + x.field = v.field; // Error +} diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.symbols b/tests/baselines/reference/intersectionsAndOptionalProperties.symbols new file mode 100644 index 0000000000000..c5504794e6ea5 --- /dev/null +++ b/tests/baselines/reference/intersectionsAndOptionalProperties.symbols @@ -0,0 +1,64 @@ +=== tests/cases/compiler/intersectionsAndOptionalProperties.ts === +declare let x: { a?: number, b: string }; +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 0, 11)) +>a : Symbol(a, Decl(intersectionsAndOptionalProperties.ts, 0, 16)) +>b : Symbol(b, Decl(intersectionsAndOptionalProperties.ts, 0, 28)) + +declare let y: { a: null, b: string }; +>y : Symbol(y, Decl(intersectionsAndOptionalProperties.ts, 1, 11)) +>a : Symbol(a, Decl(intersectionsAndOptionalProperties.ts, 1, 16)) +>b : Symbol(b, Decl(intersectionsAndOptionalProperties.ts, 1, 25)) + +declare let z: { a: null } & { b: string }; +>z : Symbol(z, Decl(intersectionsAndOptionalProperties.ts, 2, 11)) +>a : Symbol(a, Decl(intersectionsAndOptionalProperties.ts, 2, 16)) +>b : Symbol(b, Decl(intersectionsAndOptionalProperties.ts, 2, 30)) + +x = y; // Error +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 0, 11)) +>y : Symbol(y, Decl(intersectionsAndOptionalProperties.ts, 1, 11)) + +x = z; // Error +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 0, 11)) +>z : Symbol(z, Decl(intersectionsAndOptionalProperties.ts, 2, 11)) + +// Repro from #36604 + +interface To { +>To : Symbol(To, Decl(intersectionsAndOptionalProperties.ts, 5, 6)) + + field?: number; +>field : Symbol(To.field, Decl(intersectionsAndOptionalProperties.ts, 9, 14)) + + anotherField: string; +>anotherField : Symbol(To.anotherField, Decl(intersectionsAndOptionalProperties.ts, 10, 19)) +} + +type From = { field: null } & Omit; +>From : Symbol(From, Decl(intersectionsAndOptionalProperties.ts, 12, 1)) +>field : Symbol(field, Decl(intersectionsAndOptionalProperties.ts, 14, 14)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>To : Symbol(To, Decl(intersectionsAndOptionalProperties.ts, 5, 6)) + +function foo(v: From) { +>foo : Symbol(foo, Decl(intersectionsAndOptionalProperties.ts, 14, 49)) +>v : Symbol(v, Decl(intersectionsAndOptionalProperties.ts, 16, 13)) +>From : Symbol(From, Decl(intersectionsAndOptionalProperties.ts, 12, 1)) + + let x: To; +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 17, 7)) +>To : Symbol(To, Decl(intersectionsAndOptionalProperties.ts, 5, 6)) + + x = v; // Error +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 17, 7)) +>v : Symbol(v, Decl(intersectionsAndOptionalProperties.ts, 16, 13)) + + x.field = v.field; // Error +>x.field : Symbol(To.field, Decl(intersectionsAndOptionalProperties.ts, 9, 14)) +>x : Symbol(x, Decl(intersectionsAndOptionalProperties.ts, 17, 7)) +>field : Symbol(To.field, Decl(intersectionsAndOptionalProperties.ts, 9, 14)) +>v.field : Symbol(field, Decl(intersectionsAndOptionalProperties.ts, 14, 14)) +>v : Symbol(v, Decl(intersectionsAndOptionalProperties.ts, 16, 13)) +>field : Symbol(field, Decl(intersectionsAndOptionalProperties.ts, 14, 14)) +} + diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.types b/tests/baselines/reference/intersectionsAndOptionalProperties.types new file mode 100644 index 0000000000000..7f5af60c18e6f --- /dev/null +++ b/tests/baselines/reference/intersectionsAndOptionalProperties.types @@ -0,0 +1,65 @@ +=== tests/cases/compiler/intersectionsAndOptionalProperties.ts === +declare let x: { a?: number, b: string }; +>x : { a?: number | undefined; b: string; } +>a : number | undefined +>b : string + +declare let y: { a: null, b: string }; +>y : { a: null; b: string; } +>a : null +>null : null +>b : string + +declare let z: { a: null } & { b: string }; +>z : { a: null; } & { b: string; } +>a : null +>null : null +>b : string + +x = y; // Error +>x = y : { a: null; b: string; } +>x : { a?: number | undefined; b: string; } +>y : { a: null; b: string; } + +x = z; // Error +>x = z : { a: null; } & { b: string; } +>x : { a?: number | undefined; b: string; } +>z : { a: null; } & { b: string; } + +// Repro from #36604 + +interface To { + field?: number; +>field : number | undefined + + anotherField: string; +>anotherField : string +} + +type From = { field: null } & Omit; +>From : From +>field : null +>null : null + +function foo(v: From) { +>foo : (v: From) => void +>v : From + + let x: To; +>x : To + + x = v; // Error +>x = v : From +>x : To +>v : From + + x.field = v.field; // Error +>x.field = v.field : null +>x.field : number | undefined +>x : To +>field : number | undefined +>v.field : null +>v : From +>field : null +} + diff --git a/tests/cases/compiler/intersectionsAndOptionalProperties.ts b/tests/cases/compiler/intersectionsAndOptionalProperties.ts new file mode 100644 index 0000000000000..a5bc4a1580af4 --- /dev/null +++ b/tests/cases/compiler/intersectionsAndOptionalProperties.ts @@ -0,0 +1,23 @@ +// @strict: true + +declare let x: { a?: number, b: string }; +declare let y: { a: null, b: string }; +declare let z: { a: null } & { b: string }; + +x = y; // Error +x = z; // Error + +// Repro from #36604 + +interface To { + field?: number; + anotherField: string; +} + +type From = { field: null } & Omit; + +function foo(v: From) { + let x: To; + x = v; // Error + x.field = v.field; // Error +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy