From 2524c16b8bd6061af9e89b522e0545166c182938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Feb 2023 10:14:31 +0100 Subject: [PATCH 1/5] Add `NoInfer` intrinsic type --- src/compiler/checker.ts | 78 +++++--- src/compiler/types.ts | 8 +- src/lib/es5.d.ts | 5 + tests/baselines/reference/noInfer.errors.txt | 84 ++++++++ tests/baselines/reference/noInfer.symbols | 179 +++++++++++++++++ tests/baselines/reference/noInfer.types | 184 ++++++++++++++++++ .../typeInference/noInfer.ts | 48 +++++ 7 files changed, 562 insertions(+), 24 deletions(-) create mode 100644 tests/baselines/reference/noInfer.errors.txt create mode 100644 tests/baselines/reference/noInfer.symbols create mode 100644 tests/baselines/reference/noInfer.types create mode 100644 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index beb75fd16d2dc..b15e5314c7331 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -845,6 +845,7 @@ import { nodeModulesPathPart, nodeStartsNewLexicalEnvironment, NodeWithTypeArguments, + NoInferType, NonNullChain, NonNullExpression, not, @@ -1328,18 +1329,18 @@ const enum MinArgumentCountFlags { VoidIsNonOptional = 1 << 1, } -const enum IntrinsicTypeKind { +const enum StringMappingTypeKind { Uppercase, Lowercase, Capitalize, Uncapitalize } -const intrinsicTypeKinds: ReadonlyMap = new Map(Object.entries({ - Uppercase: IntrinsicTypeKind.Uppercase, - Lowercase: IntrinsicTypeKind.Lowercase, - Capitalize: IntrinsicTypeKind.Capitalize, - Uncapitalize: IntrinsicTypeKind.Uncapitalize +const stringMappingTypeKinds: ReadonlyMap = new Map(Object.entries({ + Uppercase: StringMappingTypeKind.Uppercase, + Lowercase: StringMappingTypeKind.Lowercase, + Capitalize: StringMappingTypeKind.Capitalize, + Uncapitalize: StringMappingTypeKind.Uncapitalize })); const SymbolLinks = class implements SymbolLinks { @@ -1876,7 +1877,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var enumLiteralTypes = new Map(); var indexedAccessTypes = new Map(); var templateLiteralTypes = new Map(); - var stringMappingTypes = new Map(); + var intrinsicWrapperTypes = new Map(); var substitutionTypes = new Map(); var subtypeReductionCache = new Map(); var decoratorContextOverrideTypeCache = new Map(); @@ -6526,6 +6527,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeNode = typeToTypeNodeHelper((type as StringMappingType).type, context); return symbolToTypeNode((type as StringMappingType).symbol, context, SymbolFlags.Type, [typeNode]); } + if (type.flags & TypeFlags.NoInfer) { + const typeNode = typeToTypeNodeHelper((type as NoInferType).type, context); + return symbolToTypeNode((type as NoInferType).symbol, context, SymbolFlags.Type, [typeNode]); + } if (type.flags & TypeFlags.IndexedAccess) { const objectTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).objectType, context); const indexTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).indexType, context); @@ -13727,6 +13732,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constraint = getBaseConstraint((t as StringMappingType).type); return constraint && constraint !== (t as StringMappingType).type ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType; } + if (t.flags & TypeFlags.NoInfer) { + return getBaseConstraint((t as NoInferType).type); + } if (t.flags & TypeFlags.IndexedAccess) { if (isMappedTypeGenericIndexedAccess(t)) { // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic, @@ -15168,8 +15176,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeAliasInstantiation(symbol: Symbol, typeArguments: readonly Type[] | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { const type = getDeclaredTypeOfSymbol(symbol); - if (type === intrinsicMarkerType && intrinsicTypeKinds.has(symbol.escapedName as string) && typeArguments && typeArguments.length === 1) { - return getStringMappingType(symbol, typeArguments[0]); + if (type === intrinsicMarkerType && typeArguments && typeArguments.length === 1) { + if (stringMappingTypeKinds.has(symbol.escapedName as string)) { + return getStringMappingType(symbol, typeArguments[0]); + } + return getNoInferType(symbol, typeArguments[0]); } const links = getSymbolLinks(symbol); const typeParameters = links.typeParameters!; @@ -17071,31 +17082,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type; } + function getNoInferType(symbol: Symbol, type: Type): Type { + if (!isGenericType(type)) { + return type; + } + const id = `${getSymbolId(symbol)},${getTypeId(type)}`; + let result = intrinsicWrapperTypes.get(id); + if (!result) { + intrinsicWrapperTypes.set(id, result = createNoInferType(symbol, type)); + } + return result; + } + function applyStringMapping(symbol: Symbol, str: string) { - switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { - case IntrinsicTypeKind.Uppercase: return str.toUpperCase(); - case IntrinsicTypeKind.Lowercase: return str.toLowerCase(); - case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1); - case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1); + switch (stringMappingTypeKinds.get(symbol.escapedName as string)) { + case StringMappingTypeKind.Uppercase: return str.toUpperCase(); + case StringMappingTypeKind.Lowercase: return str.toLowerCase(); + case StringMappingTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1); + case StringMappingTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1); } return str; } function applyTemplateStringMapping(symbol: Symbol, texts: readonly string[], types: readonly Type[]): [texts: readonly string[], types: readonly Type[]] { - switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { - case IntrinsicTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))]; - case IntrinsicTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))]; - case IntrinsicTypeKind.Capitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; - case IntrinsicTypeKind.Uncapitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; + switch (stringMappingTypeKinds.get(symbol.escapedName as string)) { + case StringMappingTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))]; + case StringMappingTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))]; + case StringMappingTypeKind.Capitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; + case StringMappingTypeKind.Uncapitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; } return [texts, types]; } function getStringMappingTypeForGenericType(symbol: Symbol, type: Type): Type { const id = `${getSymbolId(symbol)},${getTypeId(type)}`; - let result = stringMappingTypes.get(id); + let result = intrinsicWrapperTypes.get(id); if (!result) { - stringMappingTypes.set(id, result = createStringMappingType(symbol, type)); + intrinsicWrapperTypes.set(id, result = createStringMappingType(symbol, type)); } return result; } @@ -17106,6 +17129,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } + function createNoInferType(symbol: Symbol, type: Type) { + const result = createTypeWithSymbol(TypeFlags.NoInfer, symbol) as NoInferType; + result.type = type; + return result; + } + function createIndexedAccessType(objectType: Type, indexType: Type, accessFlags: AccessFlags, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { const type = createType(TypeFlags.IndexedAccess) as IndexedAccessType; type.objectType = objectType; @@ -18931,6 +18960,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & TypeFlags.StringMapping) { return getStringMappingType((type as StringMappingType).symbol, instantiateType((type as StringMappingType).type, mapper)); } + if (flags & TypeFlags.NoInfer) { + return getNoInferType((type as NoInferType).symbol, instantiateType((type as NoInferType).type, mapper)); + } if (flags & TypeFlags.IndexedAccess) { const newAliasSymbol = aliasSymbol || type.aliasSymbol; const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); @@ -24169,7 +24201,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferFromTypes(originalSource, originalTarget); function inferFromTypes(source: Type, target: Type): void { - if (!couldContainTypeVariables(target)) { + if (!couldContainTypeVariables(target) || source.flags & TypeFlags.NoInfer) { return; } if (source === wildcardType) { @@ -43190,7 +43222,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkExportsOnMergedDeclarations(node); checkTypeParameters(node.typeParameters); if (node.type.kind === SyntaxKind.IntrinsicKeyword) { - if (!intrinsicTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) { + if (!stringMappingTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) { error(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index df0ba774ae5b3..d55e50b9f4385 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6039,6 +6039,7 @@ export const enum TypeFlags { NonPrimitive = 1 << 26, // intrinsic object type TemplateLiteral = 1 << 27, // Template literal type StringMapping = 1 << 28, // Uppercase/Lowercase type + NoInfer = 1 << 29, // NoInfer type /** @internal */ AnyOrUnknown = Any | Unknown, @@ -6071,7 +6072,7 @@ export const enum TypeFlags { UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, - InstantiableNonPrimitive = TypeVariable | Conditional | Substitution, + InstantiableNonPrimitive = TypeVariable | Conditional | Substitution | NoInfer, InstantiablePrimitive = Index | TemplateLiteral | StringMapping, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, @@ -6606,6 +6607,11 @@ export interface StringMappingType extends InstantiableType { type: Type; } +export interface NoInferType extends InstantiableType { + symbol: Symbol; + type: Type; +} + // Type parameter substitution (TypeFlags.Substitution) // Substitution types are created for type parameters or indexed access types that occur in the // true branch of a conditional type. For example, in 'T extends string ? Foo : Bar', the diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index a74b3cb4c2111..28c58ad14889b 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1629,6 +1629,11 @@ type Capitalize = intrinsic; */ type Uncapitalize = intrinsic; +/** + * Blocks the contained type from participating in type inference. + */ +type NoInfer = intrinsic; + /** * Marker for contextual 'this' type */ diff --git a/tests/baselines/reference/noInfer.errors.txt b/tests/baselines/reference/noInfer.errors.txt new file mode 100644 index 0000000000000..7402a86e9af08 --- /dev/null +++ b/tests/baselines/reference/noInfer.errors.txt @@ -0,0 +1,84 @@ +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(4,12): error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(12,30): error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(18,16): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type '{ x: number; y: number; }'. + Property 'y' is missing in type '{ x: number; }' but required in type '{ x: number; y: number; }'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(23,22): error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. + Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(24,14): error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. + Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(32,14): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. + Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): error TS2322: Type 'NoInfer' is not assignable to type 'T'. + 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. + + +==== tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts (7 errors) ==== + export declare function foo(a: T, b: NoInfer): void + + foo('foo', 'foo') // ok + foo('foo', 'bar') // error + ~~~~~ +!!! error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. + + declare class Animal { move(): void } + declare class Dog extends Animal { woof(): void } + declare function doSomething(value: T, getDefault: () => NoInfer): void; + + doSomething(new Animal(), () => new Animal()); // ok + doSomething(new Animal(), () => new Dog()); // ok + doSomething(new Dog(), () => new Animal()); // error + ~~~~~~~~~~~~ +!!! error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. +!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:7:36: 'woof' is declared here. +!!! related TS6502 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:8:55: The expected type comes from the return type of this signature. + + declare function assertEqual(actual: T, expected: NoInfer): boolean; + + assertEqual({ x: 1 }, { x: 3 }); // ok + const g = { x: 3, y: 2 }; + assertEqual(g, { x: 3 }); // error + ~~~~~~~~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type '{ x: number; y: number; }'. +!!! error TS2345: Property 'y' is missing in type '{ x: number; }' but required in type '{ x: number; y: number; }'. +!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:17:19: 'y' is declared here. + + declare function invoke(func: (value: T) => R, value: NoInfer): R; + declare function test(value: { x: number; }): number; + + invoke(test, { x: 1, y: 2 }); // error + ~~~~ +!!! error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. +!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. + test({ x: 1, y: 2 }); // error + ~~~~ +!!! error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. +!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. + + + type Component = { props: Props; }; + declare function doWork(Component: Component, props: NoInfer): void; + declare const comp: Component<{ foo: number }>; + + doWork(comp, { foo: 42 }); // ok + doWork(comp, {}); // error + ~~ +!!! error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. +!!! error TS2345: Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. +!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:29:33: 'foo' is declared here. + + declare function mutate(callback: (a: NoInfer, b: number) => T): T; + const mutate1 = mutate((a, b) => b); + + declare class ExampleClass {} + class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'NoInfer' is not assignable to type 'T'. +!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. + } + } + + \ No newline at end of file diff --git a/tests/baselines/reference/noInfer.symbols b/tests/baselines/reference/noInfer.symbols new file mode 100644 index 0000000000000..2f239bd140560 --- /dev/null +++ b/tests/baselines/reference/noInfer.symbols @@ -0,0 +1,179 @@ +=== tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts === +export declare function foo(a: T, b: NoInfer): void +>foo : Symbol(foo, Decl(noInfer.ts, 0, 0)) +>T : Symbol(T, Decl(noInfer.ts, 0, 28)) +>a : Symbol(a, Decl(noInfer.ts, 0, 46)) +>T : Symbol(T, Decl(noInfer.ts, 0, 28)) +>b : Symbol(b, Decl(noInfer.ts, 0, 51)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 0, 28)) + +foo('foo', 'foo') // ok +>foo : Symbol(foo, Decl(noInfer.ts, 0, 0)) + +foo('foo', 'bar') // error +>foo : Symbol(foo, Decl(noInfer.ts, 0, 0)) + +declare class Animal { move(): void } +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) +>move : Symbol(Animal.move, Decl(noInfer.ts, 5, 22)) + +declare class Dog extends Animal { woof(): void } +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) +>woof : Symbol(Dog.woof, Decl(noInfer.ts, 6, 34)) + +declare function doSomething(value: T, getDefault: () => NoInfer): void; +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>T : Symbol(T, Decl(noInfer.ts, 7, 29)) +>value : Symbol(value, Decl(noInfer.ts, 7, 32)) +>T : Symbol(T, Decl(noInfer.ts, 7, 29)) +>getDefault : Symbol(getDefault, Decl(noInfer.ts, 7, 41)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 7, 29)) + +doSomething(new Animal(), () => new Animal()); // ok +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) + +doSomething(new Animal(), () => new Dog()); // ok +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) + +doSomething(new Dog(), () => new Animal()); // error +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) + +declare function assertEqual(actual: T, expected: NoInfer): boolean; +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 11, 43)) +>T : Symbol(T, Decl(noInfer.ts, 13, 29)) +>actual : Symbol(actual, Decl(noInfer.ts, 13, 32)) +>T : Symbol(T, Decl(noInfer.ts, 13, 29)) +>expected : Symbol(expected, Decl(noInfer.ts, 13, 42)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 13, 29)) + +assertEqual({ x: 1 }, { x: 3 }); // ok +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 11, 43)) +>x : Symbol(x, Decl(noInfer.ts, 15, 13)) +>x : Symbol(x, Decl(noInfer.ts, 15, 23)) + +const g = { x: 3, y: 2 }; +>g : Symbol(g, Decl(noInfer.ts, 16, 5)) +>x : Symbol(x, Decl(noInfer.ts, 16, 11)) +>y : Symbol(y, Decl(noInfer.ts, 16, 17)) + +assertEqual(g, { x: 3 }); // error +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 11, 43)) +>g : Symbol(g, Decl(noInfer.ts, 16, 5)) +>x : Symbol(x, Decl(noInfer.ts, 17, 16)) + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +>invoke : Symbol(invoke, Decl(noInfer.ts, 17, 25)) +>T : Symbol(T, Decl(noInfer.ts, 19, 24)) +>R : Symbol(R, Decl(noInfer.ts, 19, 26)) +>func : Symbol(func, Decl(noInfer.ts, 19, 30)) +>value : Symbol(value, Decl(noInfer.ts, 19, 37)) +>T : Symbol(T, Decl(noInfer.ts, 19, 24)) +>R : Symbol(R, Decl(noInfer.ts, 19, 26)) +>value : Symbol(value, Decl(noInfer.ts, 19, 52)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 19, 24)) +>R : Symbol(R, Decl(noInfer.ts, 19, 26)) + +declare function test(value: { x: number; }): number; +>test : Symbol(test, Decl(noInfer.ts, 19, 75)) +>value : Symbol(value, Decl(noInfer.ts, 20, 22)) +>x : Symbol(x, Decl(noInfer.ts, 20, 30)) + +invoke(test, { x: 1, y: 2 }); // error +>invoke : Symbol(invoke, Decl(noInfer.ts, 17, 25)) +>test : Symbol(test, Decl(noInfer.ts, 19, 75)) +>x : Symbol(x, Decl(noInfer.ts, 22, 14)) +>y : Symbol(y, Decl(noInfer.ts, 22, 20)) + +test({ x: 1, y: 2 }); // error +>test : Symbol(test, Decl(noInfer.ts, 19, 75)) +>x : Symbol(x, Decl(noInfer.ts, 23, 6)) +>y : Symbol(y, Decl(noInfer.ts, 23, 12)) + + +type Component = { props: Props; }; +>Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) +>Props : Symbol(Props, Decl(noInfer.ts, 26, 15)) +>props : Symbol(props, Decl(noInfer.ts, 26, 25)) +>Props : Symbol(Props, Decl(noInfer.ts, 26, 15)) + +declare function doWork(Component: Component, props: NoInfer): void; +>doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) +>Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) +>Component : Symbol(Component, Decl(noInfer.ts, 27, 31)) +>Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) +>Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) +>props : Symbol(props, Decl(noInfer.ts, 27, 59)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) + +declare const comp: Component<{ foo: number }>; +>comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) +>Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) +>foo : Symbol(foo, Decl(noInfer.ts, 28, 31)) + +doWork(comp, { foo: 42 }); // ok +>doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) +>comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) +>foo : Symbol(foo, Decl(noInfer.ts, 30, 14)) + +doWork(comp, {}); // error +>doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) +>comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +>mutate : Symbol(mutate, Decl(noInfer.ts, 31, 17)) +>T : Symbol(T, Decl(noInfer.ts, 33, 24)) +>callback : Symbol(callback, Decl(noInfer.ts, 33, 27)) +>a : Symbol(a, Decl(noInfer.ts, 33, 38)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 33, 24)) +>b : Symbol(b, Decl(noInfer.ts, 33, 52)) +>T : Symbol(T, Decl(noInfer.ts, 33, 24)) +>T : Symbol(T, Decl(noInfer.ts, 33, 24)) + +const mutate1 = mutate((a, b) => b); +>mutate1 : Symbol(mutate1, Decl(noInfer.ts, 34, 5)) +>mutate : Symbol(mutate, Decl(noInfer.ts, 31, 17)) +>a : Symbol(a, Decl(noInfer.ts, 34, 24)) +>b : Symbol(b, Decl(noInfer.ts, 34, 26)) +>b : Symbol(b, Decl(noInfer.ts, 34, 26)) + +declare class ExampleClass {} +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 34, 36)) +>T : Symbol(T, Decl(noInfer.ts, 36, 27)) + +class OkClass { +>OkClass : Symbol(OkClass, Decl(noInfer.ts, 36, 32)) +>T : Symbol(T, Decl(noInfer.ts, 37, 14)) + + constructor(private clazz: ExampleClass, private _value: NoInfer) {} +>clazz : Symbol(OkClass.clazz, Decl(noInfer.ts, 38, 16)) +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 34, 36)) +>T : Symbol(T, Decl(noInfer.ts, 37, 14)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 37, 14)) + + get value(): T { +>value : Symbol(OkClass.value, Decl(noInfer.ts, 38, 78)) +>T : Symbol(T, Decl(noInfer.ts, 37, 14)) + + return this._value; // ok +>this._value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) +>this : Symbol(OkClass, Decl(noInfer.ts, 36, 32)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) + } +} + + diff --git a/tests/baselines/reference/noInfer.types b/tests/baselines/reference/noInfer.types new file mode 100644 index 0000000000000..9d1eb8cbf8388 --- /dev/null +++ b/tests/baselines/reference/noInfer.types @@ -0,0 +1,184 @@ +=== tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts === +export declare function foo(a: T, b: NoInfer): void +>foo : (a: T, b: NoInfer) => void +>a : T +>b : NoInfer + +foo('foo', 'foo') // ok +>foo('foo', 'foo') : void +>foo : (a: T, b: NoInfer) => void +>'foo' : "foo" +>'foo' : "foo" + +foo('foo', 'bar') // error +>foo('foo', 'bar') : void +>foo : (a: T, b: NoInfer) => void +>'foo' : "foo" +>'bar' : "bar" + +declare class Animal { move(): void } +>Animal : Animal +>move : () => void + +declare class Dog extends Animal { woof(): void } +>Dog : Dog +>Animal : Animal +>woof : () => void + +declare function doSomething(value: T, getDefault: () => NoInfer): void; +>doSomething : (value: T, getDefault: () => NoInfer) => void +>value : T +>getDefault : () => NoInfer + +doSomething(new Animal(), () => new Animal()); // ok +>doSomething(new Animal(), () => new Animal()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Animal() : Animal +>Animal : typeof Animal +>() => new Animal() : () => Animal +>new Animal() : Animal +>Animal : typeof Animal + +doSomething(new Animal(), () => new Dog()); // ok +>doSomething(new Animal(), () => new Dog()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Animal() : Animal +>Animal : typeof Animal +>() => new Dog() : () => Dog +>new Dog() : Dog +>Dog : typeof Dog + +doSomething(new Dog(), () => new Animal()); // error +>doSomething(new Dog(), () => new Animal()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Dog() : Dog +>Dog : typeof Dog +>() => new Animal() : () => Animal +>new Animal() : Animal +>Animal : typeof Animal + +declare function assertEqual(actual: T, expected: NoInfer): boolean; +>assertEqual : (actual: T, expected: NoInfer) => boolean +>actual : T +>expected : NoInfer + +assertEqual({ x: 1 }, { x: 3 }); // ok +>assertEqual({ x: 1 }, { x: 3 }) : boolean +>assertEqual : (actual: T, expected: NoInfer) => boolean +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +>{ x: 3 } : { x: number; } +>x : number +>3 : 3 + +const g = { x: 3, y: 2 }; +>g : { x: number; y: number; } +>{ x: 3, y: 2 } : { x: number; y: number; } +>x : number +>3 : 3 +>y : number +>2 : 2 + +assertEqual(g, { x: 3 }); // error +>assertEqual(g, { x: 3 }) : boolean +>assertEqual : (actual: T, expected: NoInfer) => boolean +>g : { x: number; y: number; } +>{ x: 3 } : { x: number; } +>x : number +>3 : 3 + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +>invoke : (func: (value: T) => R, value: NoInfer) => R +>func : (value: T) => R +>value : T +>value : NoInfer + +declare function test(value: { x: number; }): number; +>test : (value: { x: number;}) => number +>value : { x: number; } +>x : number + +invoke(test, { x: 1, y: 2 }); // error +>invoke(test, { x: 1, y: 2 }) : number +>invoke : (func: (value: T) => R, value: NoInfer) => R +>test : (value: { x: number; }) => number +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + +test({ x: 1, y: 2 }); // error +>test({ x: 1, y: 2 }) : number +>test : (value: { x: number; }) => number +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + + +type Component = { props: Props; }; +>Component : Component +>props : Props + +declare function doWork(Component: Component, props: NoInfer): void; +>doWork : (Component: Component, props: NoInfer) => void +>Component : Component +>props : NoInfer + +declare const comp: Component<{ foo: number }>; +>comp : Component<{ foo: number; }> +>foo : number + +doWork(comp, { foo: 42 }); // ok +>doWork(comp, { foo: 42 }) : void +>doWork : (Component: Component, props: NoInfer) => void +>comp : Component<{ foo: number; }> +>{ foo: 42 } : { foo: number; } +>foo : number +>42 : 42 + +doWork(comp, {}); // error +>doWork(comp, {}) : void +>doWork : (Component: Component, props: NoInfer) => void +>comp : Component<{ foo: number; }> +>{} : {} + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +>mutate : (callback: (a: NoInfer, b: number) => T) => T +>callback : (a: NoInfer, b: number) => T +>a : NoInfer +>b : number + +const mutate1 = mutate((a, b) => b); +>mutate1 : unknown +>mutate((a, b) => b) : unknown +>mutate : (callback: (a: NoInfer, b: number) => T) => T +>(a, b) => b : (a: unknown, b: number) => number +>a : unknown +>b : number +>b : number + +declare class ExampleClass {} +>ExampleClass : ExampleClass + +class OkClass { +>OkClass : OkClass + + constructor(private clazz: ExampleClass, private _value: NoInfer) {} +>clazz : ExampleClass +>_value : NoInfer + + get value(): T { +>value : T + + return this._value; // ok +>this._value : NoInfer +>this : this +>_value : NoInfer + } +} + + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts new file mode 100644 index 0000000000000..230bcf3f88320 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts @@ -0,0 +1,48 @@ +// @strict: true +// @noEmit: true + +export declare function foo(a: T, b: NoInfer): void + +foo('foo', 'foo') // ok +foo('foo', 'bar') // error + +declare class Animal { move(): void } +declare class Dog extends Animal { woof(): void } +declare function doSomething(value: T, getDefault: () => NoInfer): void; + +doSomething(new Animal(), () => new Animal()); // ok +doSomething(new Animal(), () => new Dog()); // ok +doSomething(new Dog(), () => new Animal()); // error + +declare function assertEqual(actual: T, expected: NoInfer): boolean; + +assertEqual({ x: 1 }, { x: 3 }); // ok +const g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +declare function test(value: { x: number; }): number; + +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error + + +type Component = { props: Props; }; +declare function doWork(Component: Component, props: NoInfer): void; +declare const comp: Component<{ foo: number }>; + +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +const mutate1 = mutate((a, b) => b); + +declare class ExampleClass {} +class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + } +} + From 235f4de4588d1b86b7cb7d40fa01c7ffdffb4717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Feb 2023 14:21:07 +0100 Subject: [PATCH 2/5] Do not report errors on NonInfer not being able to use the instrinsic keyword --- 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 b15e5314c7331..af0fde026d5c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -43222,7 +43222,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkExportsOnMergedDeclarations(node); checkTypeParameters(node.typeParameters); if (node.type.kind === SyntaxKind.IntrinsicKeyword) { - if (!stringMappingTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) { + if (!stringMappingTypeKinds.has(node.name.escapedText as string) && (node.name.escapedText as string) !== "NoInfer" || length(node.typeParameters) !== 1) { error(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); } } From 3fffd847718fe5f93233366299d20d6319448337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Feb 2023 14:38:16 +0100 Subject: [PATCH 3/5] Include emit in the test --- tests/baselines/reference/noInfer.errors.txt | 41 ++-- tests/baselines/reference/noInfer.js | 120 +++++++++++ tests/baselines/reference/noInfer.symbols | 204 +++++++++--------- tests/baselines/reference/noInfer.types | 33 +-- .../typeInference/noInfer.ts | 34 +-- 5 files changed, 285 insertions(+), 147 deletions(-) create mode 100644 tests/baselines/reference/noInfer.js diff --git a/tests/baselines/reference/noInfer.errors.txt b/tests/baselines/reference/noInfer.errors.txt index 7402a86e9af08..d04b849d24b34 100644 --- a/tests/baselines/reference/noInfer.errors.txt +++ b/tests/baselines/reference/noInfer.errors.txt @@ -6,9 +6,9 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(23,22): Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(24,14): error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. -tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(32,14): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(31,14): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. -tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): error TS2322: Type 'NoInfer' is not assignable to type 'T'. +tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(41,9): error TS2322: Type 'NoInfer' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. @@ -20,19 +20,19 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): ~~~~~ !!! error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. - declare class Animal { move(): void } - declare class Dog extends Animal { woof(): void } - declare function doSomething(value: T, getDefault: () => NoInfer): void; + export declare class Animal { move(): void } + export declare class Dog extends Animal { woof(): void } + export declare function doSomething(value: T, getDefault: () => NoInfer): void; doSomething(new Animal(), () => new Animal()); // ok doSomething(new Animal(), () => new Dog()); // ok doSomething(new Dog(), () => new Animal()); // error ~~~~~~~~~~~~ !!! error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. -!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:7:36: 'woof' is declared here. -!!! related TS6502 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:8:55: The expected type comes from the return type of this signature. +!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:7:43: 'woof' is declared here. +!!! related TS6502 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:8:62: The expected type comes from the return type of this signature. - declare function assertEqual(actual: T, expected: NoInfer): boolean; + export declare function assertEqual(actual: T, expected: NoInfer): boolean; assertEqual({ x: 1 }, { x: 3 }); // ok const g = { x: 3, y: 2 }; @@ -42,8 +42,8 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): !!! error TS2345: Property 'y' is missing in type '{ x: number; }' but required in type '{ x: number; y: number; }'. !!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:17:19: 'y' is declared here. - declare function invoke(func: (value: T) => R, value: NoInfer): R; - declare function test(value: { x: number; }): number; + export declare function invoke(func: (value: T) => R, value: NoInfer): R; + export declare function test(value: { x: number; }): number; invoke(test, { x: 1, y: 2 }); // error ~~~~ @@ -54,23 +54,22 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): !!! error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type '{ x: number; }'. !!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. - - type Component = { props: Props; }; - declare function doWork(Component: Component, props: NoInfer): void; - declare const comp: Component<{ foo: number }>; + export type Component = { props: Props; }; + export declare function doWork(Component: Component, props: NoInfer): void; + export declare const comp: Component<{ foo: number }>; doWork(comp, { foo: 42 }); // ok doWork(comp, {}); // error ~~ !!! error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. !!! error TS2345: Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. -!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:29:33: 'foo' is declared here. +!!! related TS2728 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts:28:40: 'foo' is declared here. - declare function mutate(callback: (a: NoInfer, b: number) => T): T; - const mutate1 = mutate((a, b) => b); + export declare function mutate(callback: (a: NoInfer, b: number) => T): T; + export const mutate1 = mutate((a, b) => b); - declare class ExampleClass {} - class OkClass { + export declare class ExampleClass {} + export class OkClass { constructor(private clazz: ExampleClass, private _value: NoInfer) {} get value(): T { @@ -80,5 +79,7 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(42,9): !!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. } } - + export class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} + } \ No newline at end of file diff --git a/tests/baselines/reference/noInfer.js b/tests/baselines/reference/noInfer.js new file mode 100644 index 0000000000000..bd10bb96431ab --- /dev/null +++ b/tests/baselines/reference/noInfer.js @@ -0,0 +1,120 @@ +//// [noInfer.ts] +export declare function foo(a: T, b: NoInfer): void + +foo('foo', 'foo') // ok +foo('foo', 'bar') // error + +export declare class Animal { move(): void } +export declare class Dog extends Animal { woof(): void } +export declare function doSomething(value: T, getDefault: () => NoInfer): void; + +doSomething(new Animal(), () => new Animal()); // ok +doSomething(new Animal(), () => new Dog()); // ok +doSomething(new Dog(), () => new Animal()); // error + +export declare function assertEqual(actual: T, expected: NoInfer): boolean; + +assertEqual({ x: 1 }, { x: 3 }); // ok +const g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error + +export declare function invoke(func: (value: T) => R, value: NoInfer): R; +export declare function test(value: { x: number; }): number; + +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error + +export type Component = { props: Props; }; +export declare function doWork(Component: Component, props: NoInfer): void; +export declare const comp: Component<{ foo: number }>; + +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error + +export declare function mutate(callback: (a: NoInfer, b: number) => T): T; +export const mutate1 = mutate((a, b) => b); + +export declare class ExampleClass {} +export class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + } +} +export class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +} + + +//// [noInfer.js] +foo('foo', 'foo'); // ok +foo('foo', 'bar'); // error +doSomething(new Animal(), () => new Animal()); // ok +doSomething(new Animal(), () => new Dog()); // ok +doSomething(new Dog(), () => new Animal()); // error +assertEqual({ x: 1 }, { x: 3 }); // ok +const g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error +export const mutate1 = mutate((a, b) => b); +export class OkClass { + clazz; + _value; + constructor(clazz, _value) { + this.clazz = clazz; + this._value = _value; + } + get value() { + return this._value; // ok + } +} +export class OkClass2 { + clazz; + _value; + constructor(clazz, _value) { + this.clazz = clazz; + this._value = _value; + } +} + + +//// [noInfer.d.ts] +export declare function foo(a: T, b: NoInfer): void; +export declare class Animal { + move(): void; +} +export declare class Dog extends Animal { + woof(): void; +} +export declare function doSomething(value: T, getDefault: () => NoInfer): void; +export declare function assertEqual(actual: T, expected: NoInfer): boolean; +export declare function invoke(func: (value: T) => R, value: NoInfer): R; +export declare function test(value: { + x: number; +}): number; +export type Component = { + props: Props; +}; +export declare function doWork(Component: Component, props: NoInfer): void; +export declare const comp: Component<{ + foo: number; +}>; +export declare function mutate(callback: (a: NoInfer, b: number) => T): T; +export declare const mutate1: unknown; +export declare class ExampleClass { +} +export declare class OkClass { + private clazz; + private _value; + constructor(clazz: ExampleClass, _value: NoInfer); + get value(): T; +} +export declare class OkClass2 { + private clazz; + _value: NoInfer; + constructor(clazz: ExampleClass, _value: NoInfer); +} diff --git a/tests/baselines/reference/noInfer.symbols b/tests/baselines/reference/noInfer.symbols index 2f239bd140560..1bf5230532a19 100644 --- a/tests/baselines/reference/noInfer.symbols +++ b/tests/baselines/reference/noInfer.symbols @@ -14,47 +14,47 @@ foo('foo', 'foo') // ok foo('foo', 'bar') // error >foo : Symbol(foo, Decl(noInfer.ts, 0, 0)) -declare class Animal { move(): void } +export declare class Animal { move(): void } >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) ->move : Symbol(Animal.move, Decl(noInfer.ts, 5, 22)) +>move : Symbol(Animal.move, Decl(noInfer.ts, 5, 29)) -declare class Dog extends Animal { woof(): void } ->Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) +export declare class Dog extends Animal { woof(): void } +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 44)) >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) ->woof : Symbol(Dog.woof, Decl(noInfer.ts, 6, 34)) - -declare function doSomething(value: T, getDefault: () => NoInfer): void; ->doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) ->T : Symbol(T, Decl(noInfer.ts, 7, 29)) ->value : Symbol(value, Decl(noInfer.ts, 7, 32)) ->T : Symbol(T, Decl(noInfer.ts, 7, 29)) ->getDefault : Symbol(getDefault, Decl(noInfer.ts, 7, 41)) +>woof : Symbol(Dog.woof, Decl(noInfer.ts, 6, 41)) + +export declare function doSomething(value: T, getDefault: () => NoInfer): void; +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 56)) +>T : Symbol(T, Decl(noInfer.ts, 7, 36)) +>value : Symbol(value, Decl(noInfer.ts, 7, 39)) +>T : Symbol(T, Decl(noInfer.ts, 7, 36)) +>getDefault : Symbol(getDefault, Decl(noInfer.ts, 7, 48)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(noInfer.ts, 7, 29)) +>T : Symbol(T, Decl(noInfer.ts, 7, 36)) doSomething(new Animal(), () => new Animal()); // ok ->doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 56)) >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) doSomething(new Animal(), () => new Dog()); // ok ->doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 56)) >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) ->Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 44)) doSomething(new Dog(), () => new Animal()); // error ->doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 49)) ->Dog : Symbol(Dog, Decl(noInfer.ts, 5, 37)) +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 6, 56)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 5, 44)) >Animal : Symbol(Animal, Decl(noInfer.ts, 3, 17)) -declare function assertEqual(actual: T, expected: NoInfer): boolean; +export declare function assertEqual(actual: T, expected: NoInfer): boolean; >assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 11, 43)) ->T : Symbol(T, Decl(noInfer.ts, 13, 29)) ->actual : Symbol(actual, Decl(noInfer.ts, 13, 32)) ->T : Symbol(T, Decl(noInfer.ts, 13, 29)) ->expected : Symbol(expected, Decl(noInfer.ts, 13, 42)) +>T : Symbol(T, Decl(noInfer.ts, 13, 36)) +>actual : Symbol(actual, Decl(noInfer.ts, 13, 39)) +>T : Symbol(T, Decl(noInfer.ts, 13, 36)) +>expected : Symbol(expected, Decl(noInfer.ts, 13, 49)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(noInfer.ts, 13, 29)) +>T : Symbol(T, Decl(noInfer.ts, 13, 36)) assertEqual({ x: 1 }, { x: 3 }); // ok >assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 11, 43)) @@ -71,109 +71,119 @@ assertEqual(g, { x: 3 }); // error >g : Symbol(g, Decl(noInfer.ts, 16, 5)) >x : Symbol(x, Decl(noInfer.ts, 17, 16)) -declare function invoke(func: (value: T) => R, value: NoInfer): R; +export declare function invoke(func: (value: T) => R, value: NoInfer): R; >invoke : Symbol(invoke, Decl(noInfer.ts, 17, 25)) ->T : Symbol(T, Decl(noInfer.ts, 19, 24)) ->R : Symbol(R, Decl(noInfer.ts, 19, 26)) ->func : Symbol(func, Decl(noInfer.ts, 19, 30)) ->value : Symbol(value, Decl(noInfer.ts, 19, 37)) ->T : Symbol(T, Decl(noInfer.ts, 19, 24)) ->R : Symbol(R, Decl(noInfer.ts, 19, 26)) ->value : Symbol(value, Decl(noInfer.ts, 19, 52)) +>T : Symbol(T, Decl(noInfer.ts, 19, 31)) +>R : Symbol(R, Decl(noInfer.ts, 19, 33)) +>func : Symbol(func, Decl(noInfer.ts, 19, 37)) +>value : Symbol(value, Decl(noInfer.ts, 19, 44)) +>T : Symbol(T, Decl(noInfer.ts, 19, 31)) +>R : Symbol(R, Decl(noInfer.ts, 19, 33)) +>value : Symbol(value, Decl(noInfer.ts, 19, 59)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(noInfer.ts, 19, 24)) ->R : Symbol(R, Decl(noInfer.ts, 19, 26)) +>T : Symbol(T, Decl(noInfer.ts, 19, 31)) +>R : Symbol(R, Decl(noInfer.ts, 19, 33)) -declare function test(value: { x: number; }): number; ->test : Symbol(test, Decl(noInfer.ts, 19, 75)) ->value : Symbol(value, Decl(noInfer.ts, 20, 22)) ->x : Symbol(x, Decl(noInfer.ts, 20, 30)) +export declare function test(value: { x: number; }): number; +>test : Symbol(test, Decl(noInfer.ts, 19, 82)) +>value : Symbol(value, Decl(noInfer.ts, 20, 29)) +>x : Symbol(x, Decl(noInfer.ts, 20, 37)) invoke(test, { x: 1, y: 2 }); // error >invoke : Symbol(invoke, Decl(noInfer.ts, 17, 25)) ->test : Symbol(test, Decl(noInfer.ts, 19, 75)) +>test : Symbol(test, Decl(noInfer.ts, 19, 82)) >x : Symbol(x, Decl(noInfer.ts, 22, 14)) >y : Symbol(y, Decl(noInfer.ts, 22, 20)) test({ x: 1, y: 2 }); // error ->test : Symbol(test, Decl(noInfer.ts, 19, 75)) +>test : Symbol(test, Decl(noInfer.ts, 19, 82)) >x : Symbol(x, Decl(noInfer.ts, 23, 6)) >y : Symbol(y, Decl(noInfer.ts, 23, 12)) - -type Component = { props: Props; }; +export type Component = { props: Props; }; >Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) ->Props : Symbol(Props, Decl(noInfer.ts, 26, 15)) ->props : Symbol(props, Decl(noInfer.ts, 26, 25)) ->Props : Symbol(Props, Decl(noInfer.ts, 26, 15)) - -declare function doWork(Component: Component, props: NoInfer): void; ->doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) ->Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) ->Component : Symbol(Component, Decl(noInfer.ts, 27, 31)) +>Props : Symbol(Props, Decl(noInfer.ts, 25, 22)) +>props : Symbol(props, Decl(noInfer.ts, 25, 32)) +>Props : Symbol(Props, Decl(noInfer.ts, 25, 22)) + +export declare function doWork(Component: Component, props: NoInfer): void; +>doWork : Symbol(doWork, Decl(noInfer.ts, 25, 49)) +>Props : Symbol(Props, Decl(noInfer.ts, 26, 31)) +>Component : Symbol(Component, Decl(noInfer.ts, 26, 38)) >Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) ->Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) ->props : Symbol(props, Decl(noInfer.ts, 27, 59)) +>Props : Symbol(Props, Decl(noInfer.ts, 26, 31)) +>props : Symbol(props, Decl(noInfer.ts, 26, 66)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->Props : Symbol(Props, Decl(noInfer.ts, 27, 24)) +>Props : Symbol(Props, Decl(noInfer.ts, 26, 31)) -declare const comp: Component<{ foo: number }>; ->comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) +export declare const comp: Component<{ foo: number }>; +>comp : Symbol(comp, Decl(noInfer.ts, 27, 20)) >Component : Symbol(Component, Decl(noInfer.ts, 23, 21)) ->foo : Symbol(foo, Decl(noInfer.ts, 28, 31)) +>foo : Symbol(foo, Decl(noInfer.ts, 27, 38)) doWork(comp, { foo: 42 }); // ok ->doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) ->comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) ->foo : Symbol(foo, Decl(noInfer.ts, 30, 14)) +>doWork : Symbol(doWork, Decl(noInfer.ts, 25, 49)) +>comp : Symbol(comp, Decl(noInfer.ts, 27, 20)) +>foo : Symbol(foo, Decl(noInfer.ts, 29, 14)) doWork(comp, {}); // error ->doWork : Symbol(doWork, Decl(noInfer.ts, 26, 42)) ->comp : Symbol(comp, Decl(noInfer.ts, 28, 13)) - -declare function mutate(callback: (a: NoInfer, b: number) => T): T; ->mutate : Symbol(mutate, Decl(noInfer.ts, 31, 17)) ->T : Symbol(T, Decl(noInfer.ts, 33, 24)) ->callback : Symbol(callback, Decl(noInfer.ts, 33, 27)) ->a : Symbol(a, Decl(noInfer.ts, 33, 38)) +>doWork : Symbol(doWork, Decl(noInfer.ts, 25, 49)) +>comp : Symbol(comp, Decl(noInfer.ts, 27, 20)) + +export declare function mutate(callback: (a: NoInfer, b: number) => T): T; +>mutate : Symbol(mutate, Decl(noInfer.ts, 30, 17)) +>T : Symbol(T, Decl(noInfer.ts, 32, 31)) +>callback : Symbol(callback, Decl(noInfer.ts, 32, 34)) +>a : Symbol(a, Decl(noInfer.ts, 32, 45)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(noInfer.ts, 33, 24)) ->b : Symbol(b, Decl(noInfer.ts, 33, 52)) ->T : Symbol(T, Decl(noInfer.ts, 33, 24)) ->T : Symbol(T, Decl(noInfer.ts, 33, 24)) - -const mutate1 = mutate((a, b) => b); ->mutate1 : Symbol(mutate1, Decl(noInfer.ts, 34, 5)) ->mutate : Symbol(mutate, Decl(noInfer.ts, 31, 17)) ->a : Symbol(a, Decl(noInfer.ts, 34, 24)) ->b : Symbol(b, Decl(noInfer.ts, 34, 26)) ->b : Symbol(b, Decl(noInfer.ts, 34, 26)) - -declare class ExampleClass {} ->ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 34, 36)) ->T : Symbol(T, Decl(noInfer.ts, 36, 27)) - -class OkClass { ->OkClass : Symbol(OkClass, Decl(noInfer.ts, 36, 32)) ->T : Symbol(T, Decl(noInfer.ts, 37, 14)) +>T : Symbol(T, Decl(noInfer.ts, 32, 31)) +>b : Symbol(b, Decl(noInfer.ts, 32, 59)) +>T : Symbol(T, Decl(noInfer.ts, 32, 31)) +>T : Symbol(T, Decl(noInfer.ts, 32, 31)) + +export const mutate1 = mutate((a, b) => b); +>mutate1 : Symbol(mutate1, Decl(noInfer.ts, 33, 12)) +>mutate : Symbol(mutate, Decl(noInfer.ts, 30, 17)) +>a : Symbol(a, Decl(noInfer.ts, 33, 31)) +>b : Symbol(b, Decl(noInfer.ts, 33, 33)) +>b : Symbol(b, Decl(noInfer.ts, 33, 33)) + +export declare class ExampleClass {} +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 33, 43)) +>T : Symbol(T, Decl(noInfer.ts, 35, 34)) + +export class OkClass { +>OkClass : Symbol(OkClass, Decl(noInfer.ts, 35, 39)) +>T : Symbol(T, Decl(noInfer.ts, 36, 21)) constructor(private clazz: ExampleClass, private _value: NoInfer) {} ->clazz : Symbol(OkClass.clazz, Decl(noInfer.ts, 38, 16)) ->ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 34, 36)) ->T : Symbol(T, Decl(noInfer.ts, 37, 14)) ->_value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) +>clazz : Symbol(OkClass.clazz, Decl(noInfer.ts, 37, 16)) +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 33, 43)) +>T : Symbol(T, Decl(noInfer.ts, 36, 21)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 37, 47)) >NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(noInfer.ts, 37, 14)) +>T : Symbol(T, Decl(noInfer.ts, 36, 21)) get value(): T { ->value : Symbol(OkClass.value, Decl(noInfer.ts, 38, 78)) ->T : Symbol(T, Decl(noInfer.ts, 37, 14)) +>value : Symbol(OkClass.value, Decl(noInfer.ts, 37, 78)) +>T : Symbol(T, Decl(noInfer.ts, 36, 21)) return this._value; // ok ->this._value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) ->this : Symbol(OkClass, Decl(noInfer.ts, 36, 32)) ->_value : Symbol(OkClass._value, Decl(noInfer.ts, 38, 47)) +>this._value : Symbol(OkClass._value, Decl(noInfer.ts, 37, 47)) +>this : Symbol(OkClass, Decl(noInfer.ts, 35, 39)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 37, 47)) } } - +export class OkClass2 { +>OkClass2 : Symbol(OkClass2, Decl(noInfer.ts, 42, 1)) +>T : Symbol(T, Decl(noInfer.ts, 43, 22)) + + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +>clazz : Symbol(OkClass2.clazz, Decl(noInfer.ts, 44, 16)) +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 33, 43)) +>T : Symbol(T, Decl(noInfer.ts, 43, 22)) +>_value : Symbol(OkClass2._value, Decl(noInfer.ts, 44, 47)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 43, 22)) +} diff --git a/tests/baselines/reference/noInfer.types b/tests/baselines/reference/noInfer.types index 9d1eb8cbf8388..a6aac7da65544 100644 --- a/tests/baselines/reference/noInfer.types +++ b/tests/baselines/reference/noInfer.types @@ -16,16 +16,16 @@ foo('foo', 'bar') // error >'foo' : "foo" >'bar' : "bar" -declare class Animal { move(): void } +export declare class Animal { move(): void } >Animal : Animal >move : () => void -declare class Dog extends Animal { woof(): void } +export declare class Dog extends Animal { woof(): void } >Dog : Dog >Animal : Animal >woof : () => void -declare function doSomething(value: T, getDefault: () => NoInfer): void; +export declare function doSomething(value: T, getDefault: () => NoInfer): void; >doSomething : (value: T, getDefault: () => NoInfer) => void >value : T >getDefault : () => NoInfer @@ -57,7 +57,7 @@ doSomething(new Dog(), () => new Animal()); // error >new Animal() : Animal >Animal : typeof Animal -declare function assertEqual(actual: T, expected: NoInfer): boolean; +export declare function assertEqual(actual: T, expected: NoInfer): boolean; >assertEqual : (actual: T, expected: NoInfer) => boolean >actual : T >expected : NoInfer @@ -88,13 +88,13 @@ assertEqual(g, { x: 3 }); // error >x : number >3 : 3 -declare function invoke(func: (value: T) => R, value: NoInfer): R; +export declare function invoke(func: (value: T) => R, value: NoInfer): R; >invoke : (func: (value: T) => R, value: NoInfer) => R >func : (value: T) => R >value : T >value : NoInfer -declare function test(value: { x: number; }): number; +export declare function test(value: { x: number; }): number; >test : (value: { x: number;}) => number >value : { x: number; } >x : number @@ -118,17 +118,16 @@ test({ x: 1, y: 2 }); // error >y : number >2 : 2 - -type Component = { props: Props; }; +export type Component = { props: Props; }; >Component : Component >props : Props -declare function doWork(Component: Component, props: NoInfer): void; +export declare function doWork(Component: Component, props: NoInfer): void; >doWork : (Component: Component, props: NoInfer) => void >Component : Component >props : NoInfer -declare const comp: Component<{ foo: number }>; +export declare const comp: Component<{ foo: number }>; >comp : Component<{ foo: number; }> >foo : number @@ -146,13 +145,13 @@ doWork(comp, {}); // error >comp : Component<{ foo: number; }> >{} : {} -declare function mutate(callback: (a: NoInfer, b: number) => T): T; +export declare function mutate(callback: (a: NoInfer, b: number) => T): T; >mutate : (callback: (a: NoInfer, b: number) => T) => T >callback : (a: NoInfer, b: number) => T >a : NoInfer >b : number -const mutate1 = mutate((a, b) => b); +export const mutate1 = mutate((a, b) => b); >mutate1 : unknown >mutate((a, b) => b) : unknown >mutate : (callback: (a: NoInfer, b: number) => T) => T @@ -161,10 +160,10 @@ const mutate1 = mutate((a, b) => b); >b : number >b : number -declare class ExampleClass {} +export declare class ExampleClass {} >ExampleClass : ExampleClass -class OkClass { +export class OkClass { >OkClass : OkClass constructor(private clazz: ExampleClass, private _value: NoInfer) {} @@ -180,5 +179,11 @@ class OkClass { >_value : NoInfer } } +export class OkClass2 { +>OkClass2 : OkClass2 + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +>clazz : ExampleClass +>_value : NoInfer +} diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts index 230bcf3f88320..9d3fbd6f666c2 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts @@ -1,48 +1,50 @@ // @strict: true -// @noEmit: true +// @target: esnext +// @declaration: true export declare function foo(a: T, b: NoInfer): void foo('foo', 'foo') // ok foo('foo', 'bar') // error -declare class Animal { move(): void } -declare class Dog extends Animal { woof(): void } -declare function doSomething(value: T, getDefault: () => NoInfer): void; +export declare class Animal { move(): void } +export declare class Dog extends Animal { woof(): void } +export declare function doSomething(value: T, getDefault: () => NoInfer): void; doSomething(new Animal(), () => new Animal()); // ok doSomething(new Animal(), () => new Dog()); // ok doSomething(new Dog(), () => new Animal()); // error -declare function assertEqual(actual: T, expected: NoInfer): boolean; +export declare function assertEqual(actual: T, expected: NoInfer): boolean; assertEqual({ x: 1 }, { x: 3 }); // ok const g = { x: 3, y: 2 }; assertEqual(g, { x: 3 }); // error -declare function invoke(func: (value: T) => R, value: NoInfer): R; -declare function test(value: { x: number; }): number; +export declare function invoke(func: (value: T) => R, value: NoInfer): R; +export declare function test(value: { x: number; }): number; invoke(test, { x: 1, y: 2 }); // error test({ x: 1, y: 2 }); // error - -type Component = { props: Props; }; -declare function doWork(Component: Component, props: NoInfer): void; -declare const comp: Component<{ foo: number }>; +export type Component = { props: Props; }; +export declare function doWork(Component: Component, props: NoInfer): void; +export declare const comp: Component<{ foo: number }>; doWork(comp, { foo: 42 }); // ok doWork(comp, {}); // error -declare function mutate(callback: (a: NoInfer, b: number) => T): T; -const mutate1 = mutate((a, b) => b); +export declare function mutate(callback: (a: NoInfer, b: number) => T): T; +export const mutate1 = mutate((a, b) => b); -declare class ExampleClass {} -class OkClass { +export declare class ExampleClass {} +export class OkClass { constructor(private clazz: ExampleClass, private _value: NoInfer) {} get value(): T { return this._value; // ok } } - +export class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +} From f94b780c98fbd484dc320a56eca4c19c0a7b26ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Feb 2023 14:47:33 +0100 Subject: [PATCH 4/5] fixed tests --- src/harness/fourslashInterfaceImpl.ts | 1 + tests/baselines/reference/api/tsserverlibrary.d.ts | 13 +++++++++---- tests/baselines/reference/api/typescript.d.ts | 13 +++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 4cf5c58d542b7..63d5d34975859 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1214,6 +1214,7 @@ export namespace Completion { typeEntry("Lowercase"), typeEntry("Capitalize"), typeEntry("Uncapitalize"), + typeEntry("NoInfer"), interfaceEntry("ThisType"), varEntry("ArrayBuffer"), interfaceEntry("ArrayBufferTypes"), diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 34006d63b2ea5..b70c0dc271d40 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6674,6 +6674,7 @@ declare namespace ts { NonPrimitive = 67108864, TemplateLiteral = 134217728, StringMapping = 268435456, + NoInfer = 536870912, Literal = 2944, Unit = 109472, Freshable = 2976, @@ -6689,11 +6690,11 @@ declare namespace ts { UnionOrIntersection = 3145728, StructuredType = 3670016, TypeVariable = 8650752, - InstantiableNonPrimitive = 58982400, + InstantiableNonPrimitive = 595853312, InstantiablePrimitive = 406847488, - Instantiable = 465829888, - StructuredOrInstantiable = 469499904, - Narrowable = 536624127 + Instantiable = 1002700800, + StructuredOrInstantiable = 1006370816, + Narrowable = 1073495039 } type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { @@ -6888,6 +6889,10 @@ declare namespace ts { symbol: Symbol; type: Type; } + interface NoInferType extends InstantiableType { + symbol: Symbol; + type: Type; + } interface SubstitutionType extends InstantiableType { objectFlags: ObjectFlags; baseType: Type; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2201712f7c4eb..04377bb8a2f11 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2699,6 +2699,7 @@ declare namespace ts { NonPrimitive = 67108864, TemplateLiteral = 134217728, StringMapping = 268435456, + NoInfer = 536870912, Literal = 2944, Unit = 109472, Freshable = 2976, @@ -2714,11 +2715,11 @@ declare namespace ts { UnionOrIntersection = 3145728, StructuredType = 3670016, TypeVariable = 8650752, - InstantiableNonPrimitive = 58982400, + InstantiableNonPrimitive = 595853312, InstantiablePrimitive = 406847488, - Instantiable = 465829888, - StructuredOrInstantiable = 469499904, - Narrowable = 536624127 + Instantiable = 1002700800, + StructuredOrInstantiable = 1006370816, + Narrowable = 1073495039 } type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { @@ -2913,6 +2914,10 @@ declare namespace ts { symbol: Symbol; type: Type; } + interface NoInferType extends InstantiableType { + symbol: Symbol; + type: Type; + } interface SubstitutionType extends InstantiableType { objectFlags: ObjectFlags; baseType: Type; From 86448ffa49234cbe0b00be9773544d16d8777eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 25 Feb 2023 18:05:52 +0100 Subject: [PATCH 5/5] Normalize `NoInferType` --- src/compiler/checker.ts | 1 + tests/baselines/reference/noInfer.errors.txt | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index af0fde026d5c1..3aef51897beac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20101,6 +20101,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) : type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) : type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : + type.flags & TypeFlags.NoInfer ? (type as NoInferType).type : type; if (t === type) return t; type = t; diff --git a/tests/baselines/reference/noInfer.errors.txt b/tests/baselines/reference/noInfer.errors.txt index d04b849d24b34..cc01a35e69171 100644 --- a/tests/baselines/reference/noInfer.errors.txt +++ b/tests/baselines/reference/noInfer.errors.txt @@ -8,11 +8,9 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(24,14): Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(31,14): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. -tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(41,9): error TS2322: Type 'NoInfer' is not assignable to type 'T'. - 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. -==== tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts (7 errors) ==== +==== tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts (6 errors) ==== export declare function foo(a: T, b: NoInfer): void foo('foo', 'foo') // ok @@ -74,9 +72,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts(41,9): get value(): T { return this._value; // ok - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type 'NoInfer' is not assignable to type 'T'. -!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'NoInfer'. } } export class OkClass2 {