mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
Revise accessor resolution logic and error reporting (#48459)
* Revise accessor resolution logic and error reporting * Accept new baselines * Update isTypeElement * Add tests
This commit is contained in:
@@ -172,6 +172,7 @@ namespace ts {
|
||||
EnumTagType,
|
||||
ResolvedTypeArguments,
|
||||
ResolvedBaseTypes,
|
||||
WriteType,
|
||||
}
|
||||
|
||||
const enum CheckMode {
|
||||
@@ -8519,6 +8520,8 @@ namespace ts {
|
||||
return !!(target as TypeReference).resolvedTypeArguments;
|
||||
case TypeSystemPropertyName.ResolvedBaseTypes:
|
||||
return !!(target as InterfaceType).baseTypesResolved;
|
||||
case TypeSystemPropertyName.WriteType:
|
||||
return !!getSymbolLinks(target as Symbol).writeType;
|
||||
}
|
||||
return Debug.assertNever(propertyName);
|
||||
}
|
||||
@@ -9502,6 +9505,11 @@ namespace ts {
|
||||
}
|
||||
return getWidenedType(getWidenedLiteralType(checkExpression(declaration.statements[0].expression)));
|
||||
}
|
||||
if (isAccessor(declaration)) {
|
||||
// Binding of certain patterns in JS code will occasionally mark symbols as both properties
|
||||
// and accessors. Here we dispatch to accessor resolution if needed.
|
||||
return getTypeOfAccessors(symbol);
|
||||
}
|
||||
|
||||
// Handle variable, parameter or property
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
@@ -9567,9 +9575,6 @@ namespace ts {
|
||||
else if (isEnumMember(declaration)) {
|
||||
type = getTypeOfEnumMember(symbol);
|
||||
}
|
||||
else if (isAccessor(declaration)) {
|
||||
type = resolveTypeOfAccessors(symbol) || Debug.fail("Non-write accessor resolution must always produce a type");
|
||||
}
|
||||
else {
|
||||
return Debug.fail("Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + Debug.formatSymbol(symbol));
|
||||
}
|
||||
@@ -9614,97 +9619,62 @@ namespace ts {
|
||||
|
||||
function getTypeOfAccessors(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
return links.type || (links.type = getTypeOfAccessorsWorker(symbol) || Debug.fail("Read type of accessor must always produce a type"));
|
||||
}
|
||||
|
||||
function getTypeOfSetAccessor(symbol: Symbol): Type | undefined {
|
||||
const links = getSymbolLinks(symbol);
|
||||
return links.writeType || (links.writeType = getTypeOfAccessorsWorker(symbol, /*writing*/ true));
|
||||
}
|
||||
|
||||
function getTypeOfAccessorsWorker(symbol: Symbol, writing = false): Type | undefined {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
let type = resolveTypeOfAccessors(symbol, writing);
|
||||
if (!popTypeResolution()) {
|
||||
if (!links.type) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return errorType;
|
||||
}
|
||||
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
|
||||
if (getter) {
|
||||
if (getEffectiveTypeAnnotationNode(getter)) {
|
||||
error(getter.name, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
|
||||
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
|
||||
// We try to resolve a getter type annotation, a setter type annotation, or a getter function
|
||||
// body return type inference, in that order.
|
||||
let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) ||
|
||||
getAnnotatedAccessorType(getter) ||
|
||||
getAnnotatedAccessorType(setter) ||
|
||||
getter && getter.body && getReturnTypeFromBody(getter);
|
||||
if (!type) {
|
||||
if (setter && !isPrivateWithinAmbient(setter)) {
|
||||
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
else if (noImplicitAny) {
|
||||
else if (getter && !isPrivateWithinAmbient(getter)) {
|
||||
errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
type = anyType;
|
||||
}
|
||||
if (!popTypeResolution()) {
|
||||
if (getAnnotatedAccessorTypeNode(getter)) {
|
||||
error(getter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
else if (getAnnotatedAccessorTypeNode(setter)) {
|
||||
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
else if (getter && noImplicitAny) {
|
||||
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
|
||||
}
|
||||
type = anyType;
|
||||
}
|
||||
type = anyType;
|
||||
links.type = type;
|
||||
}
|
||||
return type;
|
||||
return links.type;
|
||||
}
|
||||
|
||||
function resolveTypeOfAccessors(symbol: Symbol, writing = false) {
|
||||
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
|
||||
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
|
||||
|
||||
// For write operations, prioritize type annotations on the setter
|
||||
if (writing) {
|
||||
const setterType = getAnnotatedAccessorType(setter);
|
||||
if (setterType) {
|
||||
return instantiateTypeIfNeeded(setterType, symbol);
|
||||
function getWriteTypeOfAccessors(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.writeType) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.WriteType)) {
|
||||
return errorType;
|
||||
}
|
||||
}
|
||||
// Else defer to the getter type
|
||||
|
||||
if (getter && isInJSFile(getter)) {
|
||||
const jsDocType = getTypeForDeclarationFromJSDocComment(getter);
|
||||
if (jsDocType) {
|
||||
return instantiateTypeIfNeeded(jsDocType, symbol);
|
||||
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
|
||||
let writeType = getAnnotatedAccessorType(setter);
|
||||
if (!popTypeResolution()) {
|
||||
if (getAnnotatedAccessorTypeNode(setter)) {
|
||||
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
writeType = anyType;
|
||||
}
|
||||
// Absent an explicit setter type annotation we use the read type of the accessor.
|
||||
links.writeType = writeType || getTypeOfAccessors(symbol);
|
||||
}
|
||||
|
||||
// Try to see if the user specified a return type on the get-accessor.
|
||||
const getterType = getAnnotatedAccessorType(getter);
|
||||
if (getterType) {
|
||||
return instantiateTypeIfNeeded(getterType, symbol);
|
||||
}
|
||||
|
||||
// If the user didn't specify a return type, try to use the set-accessor's parameter type.
|
||||
const setterType = getAnnotatedAccessorType(setter);
|
||||
if (setterType) {
|
||||
return setterType;
|
||||
}
|
||||
|
||||
// If there are no specified types, try to infer it from the body of the get accessor if it exists.
|
||||
if (getter && getter.body) {
|
||||
const returnTypeFromBody = getReturnTypeFromBody(getter);
|
||||
return instantiateTypeIfNeeded(returnTypeFromBody, symbol);
|
||||
}
|
||||
|
||||
// Otherwise, fall back to 'any'.
|
||||
if (setter) {
|
||||
if (!isPrivateWithinAmbient(setter)) {
|
||||
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
return anyType;
|
||||
}
|
||||
else if (getter) {
|
||||
Debug.assert(!!getter, "there must exist a getter as we are current checking either setter or getter in this function");
|
||||
if (!isPrivateWithinAmbient(getter)) {
|
||||
errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
|
||||
}
|
||||
return anyType;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
function instantiateTypeIfNeeded(type: Type, symbol: Symbol) {
|
||||
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
|
||||
const links = getSymbolLinks(symbol);
|
||||
return instantiateType(type, links.mapper);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
return links.writeType;
|
||||
}
|
||||
|
||||
function getBaseTypeVariableOfClass(symbol: Symbol) {
|
||||
@@ -9792,17 +9762,12 @@ namespace ts {
|
||||
|
||||
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return links.type = errorType;
|
||||
}
|
||||
let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper);
|
||||
if (!popTypeResolution()) {
|
||||
type = reportCircularityError(symbol);
|
||||
}
|
||||
links.type = type;
|
||||
}
|
||||
return links.type;
|
||||
return links.type || (links.type = instantiateType(getTypeOfSymbol(links.target!), links.mapper));
|
||||
}
|
||||
|
||||
function getWriteTypeOfInstantiatedSymbol(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
return links.writeType || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper));
|
||||
}
|
||||
|
||||
function reportCircularityError(symbol: Symbol) {
|
||||
@@ -9845,36 +9810,23 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Distinct write types come only from set accessors, but union and intersection
|
||||
* properties deriving from set accessors will either pre-compute or defer the
|
||||
* union or intersection of the writeTypes of their constituents. To account for
|
||||
* this, we will assume that any deferred type or transient symbol may have a
|
||||
* `writeType` (or a deferred write type ready to be computed) that should be
|
||||
* used before looking for set accessor declarations.
|
||||
* Distinct write types come only from set accessors, but synthetic union and intersection
|
||||
* properties deriving from set accessors will either pre-compute or defer the union or
|
||||
* intersection of the writeTypes of their constituents.
|
||||
*/
|
||||
function getWriteTypeOfSymbol(symbol: Symbol): Type {
|
||||
const checkFlags = getCheckFlags(symbol);
|
||||
if (checkFlags & CheckFlags.DeferredType) {
|
||||
const writeType = getWriteTypeOfSymbolWithDeferredType(symbol);
|
||||
if (writeType) {
|
||||
return writeType;
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Property) {
|
||||
return checkFlags & CheckFlags.SyntheticProperty ?
|
||||
checkFlags & CheckFlags.DeferredType ?
|
||||
getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
|
||||
(symbol as TransientSymbol).writeType || (symbol as TransientSymbol).type! :
|
||||
getTypeOfSymbol(symbol);
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Transient) {
|
||||
const { writeType } = symbol as TransientSymbol;
|
||||
if (writeType) {
|
||||
return writeType;
|
||||
}
|
||||
}
|
||||
return getSetAccessorTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
function getSetAccessorTypeOfSymbol(symbol: Symbol): Type {
|
||||
if (symbol.flags & SymbolFlags.Accessor) {
|
||||
const type = getTypeOfSetAccessor(symbol);
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
return checkFlags & CheckFlags.Instantiated ?
|
||||
getWriteTypeOfInstantiatedSymbol(symbol) :
|
||||
getWriteTypeOfAccessors(symbol);
|
||||
}
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
@@ -25237,7 +25189,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
if (isDeclarationName(location) && isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) {
|
||||
return resolveTypeOfAccessors(location.parent.symbol, /*writing*/ true)!;
|
||||
return getWriteTypeOfAccessors(location.parent.symbol);
|
||||
}
|
||||
// The location isn't a reference to the given symbol, meaning we're being asked
|
||||
// a hypothetical question of what type the symbol would have if there was a reference
|
||||
|
||||
@@ -1335,7 +1335,9 @@ namespace ts {
|
||||
|| kind === SyntaxKind.CallSignature
|
||||
|| kind === SyntaxKind.PropertySignature
|
||||
|| kind === SyntaxKind.MethodSignature
|
||||
|| kind === SyntaxKind.IndexSignature;
|
||||
|| kind === SyntaxKind.IndexSignature
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor;
|
||||
}
|
||||
|
||||
export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
tests/cases/compiler/circularAccessorAnnotations.ts(2,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/circularAccessorAnnotations.ts(6,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/circularAccessorAnnotations.ts(15,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/circularAccessorAnnotations.ts(19,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
|
||||
|
||||
==== tests/cases/compiler/circularAccessorAnnotations.ts (4 errors) ====
|
||||
declare const c1: {
|
||||
get foo(): typeof c1.foo;
|
||||
~~~
|
||||
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
}
|
||||
|
||||
declare const c2: {
|
||||
set foo(value: typeof c2.foo);
|
||||
~~~
|
||||
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
}
|
||||
|
||||
declare const c3: {
|
||||
get foo(): string;
|
||||
set foo(value: typeof c3.foo);
|
||||
}
|
||||
|
||||
type T1 = {
|
||||
get foo(): T1["foo"];
|
||||
~~~
|
||||
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
}
|
||||
|
||||
type T2 = {
|
||||
set foo(value: T2["foo"]);
|
||||
~~~
|
||||
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
|
||||
}
|
||||
|
||||
type T3 = {
|
||||
get foo(): string;
|
||||
set foo(value: T3["foo"]);
|
||||
}
|
||||
|
||||
53
tests/baselines/reference/circularAccessorAnnotations.js
Normal file
53
tests/baselines/reference/circularAccessorAnnotations.js
Normal file
@@ -0,0 +1,53 @@
|
||||
//// [circularAccessorAnnotations.ts]
|
||||
declare const c1: {
|
||||
get foo(): typeof c1.foo;
|
||||
}
|
||||
|
||||
declare const c2: {
|
||||
set foo(value: typeof c2.foo);
|
||||
}
|
||||
|
||||
declare const c3: {
|
||||
get foo(): string;
|
||||
set foo(value: typeof c3.foo);
|
||||
}
|
||||
|
||||
type T1 = {
|
||||
get foo(): T1["foo"];
|
||||
}
|
||||
|
||||
type T2 = {
|
||||
set foo(value: T2["foo"]);
|
||||
}
|
||||
|
||||
type T3 = {
|
||||
get foo(): string;
|
||||
set foo(value: T3["foo"]);
|
||||
}
|
||||
|
||||
|
||||
//// [circularAccessorAnnotations.js]
|
||||
"use strict";
|
||||
|
||||
|
||||
//// [circularAccessorAnnotations.d.ts]
|
||||
declare const c1: {
|
||||
get foo(): typeof c1.foo;
|
||||
};
|
||||
declare const c2: {
|
||||
set foo(value: typeof c2.foo);
|
||||
};
|
||||
declare const c3: {
|
||||
get foo(): string;
|
||||
set foo(value: typeof c3.foo);
|
||||
};
|
||||
declare type T1 = {
|
||||
get foo(): T1["foo"];
|
||||
};
|
||||
declare type T2 = {
|
||||
set foo(value: T2["foo"]);
|
||||
};
|
||||
declare type T3 = {
|
||||
get foo(): string;
|
||||
set foo(value: T3["foo"]);
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
=== tests/cases/compiler/circularAccessorAnnotations.ts ===
|
||||
declare const c1: {
|
||||
>c1 : Symbol(c1, Decl(circularAccessorAnnotations.ts, 0, 13))
|
||||
|
||||
get foo(): typeof c1.foo;
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
|
||||
>c1.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
|
||||
>c1 : Symbol(c1, Decl(circularAccessorAnnotations.ts, 0, 13))
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
|
||||
}
|
||||
|
||||
declare const c2: {
|
||||
>c2 : Symbol(c2, Decl(circularAccessorAnnotations.ts, 4, 13))
|
||||
|
||||
set foo(value: typeof c2.foo);
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
|
||||
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 5, 12))
|
||||
>c2.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
|
||||
>c2 : Symbol(c2, Decl(circularAccessorAnnotations.ts, 4, 13))
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
|
||||
}
|
||||
|
||||
declare const c3: {
|
||||
>c3 : Symbol(c3, Decl(circularAccessorAnnotations.ts, 8, 13))
|
||||
|
||||
get foo(): string;
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
|
||||
|
||||
set foo(value: typeof c3.foo);
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
|
||||
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 10, 12))
|
||||
>c3.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
|
||||
>c3 : Symbol(c3, Decl(circularAccessorAnnotations.ts, 8, 13))
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
|
||||
}
|
||||
|
||||
type T1 = {
|
||||
>T1 : Symbol(T1, Decl(circularAccessorAnnotations.ts, 11, 1))
|
||||
|
||||
get foo(): T1["foo"];
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 13, 11))
|
||||
>T1 : Symbol(T1, Decl(circularAccessorAnnotations.ts, 11, 1))
|
||||
}
|
||||
|
||||
type T2 = {
|
||||
>T2 : Symbol(T2, Decl(circularAccessorAnnotations.ts, 15, 1))
|
||||
|
||||
set foo(value: T2["foo"]);
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 17, 11))
|
||||
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 18, 12))
|
||||
>T2 : Symbol(T2, Decl(circularAccessorAnnotations.ts, 15, 1))
|
||||
}
|
||||
|
||||
type T3 = {
|
||||
>T3 : Symbol(T3, Decl(circularAccessorAnnotations.ts, 19, 1))
|
||||
|
||||
get foo(): string;
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 21, 11), Decl(circularAccessorAnnotations.ts, 22, 22))
|
||||
|
||||
set foo(value: T3["foo"]);
|
||||
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 21, 11), Decl(circularAccessorAnnotations.ts, 22, 22))
|
||||
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 23, 12))
|
||||
>T3 : Symbol(T3, Decl(circularAccessorAnnotations.ts, 19, 1))
|
||||
}
|
||||
|
||||
62
tests/baselines/reference/circularAccessorAnnotations.types
Normal file
62
tests/baselines/reference/circularAccessorAnnotations.types
Normal file
@@ -0,0 +1,62 @@
|
||||
=== tests/cases/compiler/circularAccessorAnnotations.ts ===
|
||||
declare const c1: {
|
||||
>c1 : { readonly foo: any; }
|
||||
|
||||
get foo(): typeof c1.foo;
|
||||
>foo : any
|
||||
>c1.foo : any
|
||||
>c1 : { readonly foo: any; }
|
||||
>foo : any
|
||||
}
|
||||
|
||||
declare const c2: {
|
||||
>c2 : { foo: any; }
|
||||
|
||||
set foo(value: typeof c2.foo);
|
||||
>foo : any
|
||||
>value : any
|
||||
>c2.foo : any
|
||||
>c2 : { foo: any; }
|
||||
>foo : any
|
||||
}
|
||||
|
||||
declare const c3: {
|
||||
>c3 : { foo: string; }
|
||||
|
||||
get foo(): string;
|
||||
>foo : string
|
||||
|
||||
set foo(value: typeof c3.foo);
|
||||
>foo : string
|
||||
>value : string
|
||||
>c3.foo : string
|
||||
>c3 : { foo: string; }
|
||||
>foo : string
|
||||
}
|
||||
|
||||
type T1 = {
|
||||
>T1 : T1
|
||||
|
||||
get foo(): T1["foo"];
|
||||
>foo : any
|
||||
}
|
||||
|
||||
type T2 = {
|
||||
>T2 : T2
|
||||
|
||||
set foo(value: T2["foo"]);
|
||||
>foo : any
|
||||
>value : any
|
||||
}
|
||||
|
||||
type T3 = {
|
||||
>T3 : T3
|
||||
|
||||
get foo(): string;
|
||||
>foo : string
|
||||
|
||||
set foo(value: T3["foo"]);
|
||||
>foo : string
|
||||
>value : string
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(2,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(6,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(11,11): error TS2589: Type instantiation is excessively deep and possibly infinite.
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(18,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(22,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(37,24): error TS2313: Type parameter 'T' has a circular constraint.
|
||||
@@ -15,13 +15,13 @@ tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(37,30): error
|
||||
|
||||
type T2<K extends "x" | "y"> = {
|
||||
x: T2<K>[K]; // Error
|
||||
~
|
||||
!!! error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
|
||||
y: number;
|
||||
}
|
||||
|
||||
declare let x2: T2<"x">;
|
||||
let x2x = x2.x;
|
||||
~~~~
|
||||
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
|
||||
|
||||
interface T3<T extends T3<T>> {
|
||||
x: T["x"];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(4,9): error TS2589: Type instantiation is excessively deep and possibly infinite.
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"fals
|
||||
// Repro from #14837
|
||||
|
||||
type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
|
||||
~~~~~~
|
||||
!!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
|
||||
let f1: Foo<"true", {}>;
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
|
||||
let f2: Foo<"false", {}>;
|
||||
~~~~~~~
|
||||
!!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
|
||||
|
||||
28
tests/cases/compiler/circularAccessorAnnotations.ts
Normal file
28
tests/cases/compiler/circularAccessorAnnotations.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
declare const c1: {
|
||||
get foo(): typeof c1.foo;
|
||||
}
|
||||
|
||||
declare const c2: {
|
||||
set foo(value: typeof c2.foo);
|
||||
}
|
||||
|
||||
declare const c3: {
|
||||
get foo(): string;
|
||||
set foo(value: typeof c3.foo);
|
||||
}
|
||||
|
||||
type T1 = {
|
||||
get foo(): T1["foo"];
|
||||
}
|
||||
|
||||
type T2 = {
|
||||
set foo(value: T2["foo"]);
|
||||
}
|
||||
|
||||
type T3 = {
|
||||
get foo(): string;
|
||||
set foo(value: T3["foo"]);
|
||||
}
|
||||
Reference in New Issue
Block a user