diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 10ddb3c0c88b4..4c57dd37910f2 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -598,6 +598,7 @@ type Checker struct { SignatureCount uint32 TotalInstantiationCount uint32 instantiationCount uint32 + memberLayoutCount uint32 instantiationStack []*Type conditionalConstraintDepth uint32 inlineLevel int @@ -648,6 +649,7 @@ type Checker struct { reverseMappedCache map[ReverseMappedTypeKey]*Type reverseHomomorphicMappedCache map[ReverseMappedTypeKey]*Type iterationTypesCache map[IterationTypesKey]IterationTypes + memberLayoutCache map[CacheHashKey]*MemberLayout markerTypes collections.Set[*Type] resolvingExplicitTypeOfSymbol collections.Set[*ast.Symbol] constructorOrFunctionChecked collections.Set[*ast.Symbol] @@ -690,6 +692,9 @@ type Checker struct { outerTypeParameterListArena core.Arena[[]*Type] valueSymbolExtraArena core.Arena[valueSymbolExtra] structuredTypeExtraArena core.Arena[structuredTypeExtra] + lazyStateArena core.Arena[LazyState] + memberLayoutArena core.Arena[MemberLayout] + layoutMemberInfos map[string]MemberInfo freeTypeSets *temporaryTypeSet freePropertyCounts *temporaryPropertyCounts mergedSymbols map[*ast.Symbol]*ast.Symbol @@ -4587,8 +4592,8 @@ func (c *Checker) getTypeWithoutSignatures(t *Type) *Type { if len(resolved.getSignatures()) != 0 { result := c.newObjectType(ObjectFlagsAnonymous, t.symbol) result.objectFlags |= ObjectFlagsMembersResolved - result.AsObjectType().members = resolved.members - result.AsObjectType().properties = resolved.properties + result.AsObjectType().members = resolved.getMembers() + result.AsObjectType().properties = resolved.getProperties() return result } case t.flags&TypeFlagsIntersection != 0: @@ -10925,7 +10930,7 @@ func (c *Checker) getInstantiationExpressionType(exprType *Type, node *ast.Node) debug.Assert(t.symbol != nil, "Instantiation expression source type must have a symbol") symbol.SetDeclarations(t.symbol.Declarations()) result := c.newObjectType(ObjectFlagsAnonymous|ObjectFlagsInstantiationExpressionType, symbol) - c.setStructuredTypeMembers(result, resolved.members, callSignatures, constructSignatures, resolved.getIndexInfos()) + c.setStructuredTypeMembers(result, resolved.getMembers(), callSignatures, constructSignatures, resolved.getIndexInfos()) result.AsInstantiationExpressionType().node = node return result } @@ -16137,7 +16142,7 @@ func (c *Checker) cloneTypeAsModuleType(symbol *ast.Symbol, moduleType *Type, re links.target = symbol links.originatingImport = referenceParent resolvedModuleType := c.resolveStructuredTypeMembers(moduleType) - c.valueSymbolLinks.Get(result).resolvedType = c.newAnonymousType(result, resolvedModuleType.members, nil, nil, resolvedModuleType.getIndexInfos()) + c.valueSymbolLinks.Get(result).resolvedType = c.newAnonymousType(result, resolvedModuleType.getMembers(), nil, nil, resolvedModuleType.getIndexInfos()) return result } @@ -19289,7 +19294,34 @@ func (c *Checker) getPropertiesOfType(t *Type) []*ast.Symbol { func (c *Checker) getPropertiesOfObjectType(t *Type) []*ast.Symbol { if t.flags&TypeFlagsObject != 0 { - return c.resolveStructuredTypeMembers(t).properties + return c.resolveStructuredTypeMembers(t).getProperties() + } + return nil +} + +// For classes and interfaces, the layout properties of the type are uninstantiated symbols from +// the shared member layout. When operations only process the declaration, flags, and/or name +// of members (and not their type), using the layout properties helps defer instantiation of +// the members. For example, `keyof T` can be computed entirely from layout properties. +func (c *Checker) getLayoutPropertiesOfType(t *Type) []*ast.Symbol { + t = c.getReducedApparentType(t) + lazy := c.getLazyStateOfType(t) + if lazy == nil { + return c.getPropertiesOfType(t) + } + layout := lazy.layout + if layout.layoutProperties == nil { + layout.layoutProperties = make([]*ast.Symbol, len(layout.memberInfos)) + for i, memberInfo := range layout.memberInfos { + layout.layoutProperties[i] = memberInfo.symbol + } + } + return layout.layoutProperties +} + +func (c *Checker) getLazyStateOfType(t *Type) *LazyState { + if t.flags&TypeFlagsObject != 0 { + return c.resolveStructuredTypeMembers(t).getLazyState() } return nil } @@ -19337,7 +19369,7 @@ func (c *Checker) getPropertyOfTypeEx(t *Type, name string, skipObjectFunctionPr switch { case t.flags&TypeFlagsObject != 0: resolved := c.resolveStructuredTypeMembers(t) - symbol := resolved.members[name] + symbol := resolved.getMember(name) if symbol != nil { if !includeTypeOnlyMembers && t.symbol != nil && t.symbol.Flags()&ast.SymbolFlagsValueModule != 0 && c.moduleSymbolLinks.Get(t.symbol).typeOnlyExportStarMap[name] != nil { // If this is the type of a module, `resolved.members.get(name)` might have effectively skipped over @@ -19503,10 +19535,8 @@ func (c *Checker) resolveStructuredTypeMembers(t *Type) *StructuredType { switch { case t.flags&TypeFlagsObject != 0: switch { - case t.objectFlags&ObjectFlagsReference != 0: - c.resolveTypeReferenceMembers(t) - case t.objectFlags&ObjectFlagsClassOrInterface != 0: - c.resolveClassOrInterfaceMembers(t) + case t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0: + c.resolveObjectTypeMembers(t) case t.objectFlags&ObjectFlagsReverseMapped != 0: c.resolveReverseMappedTypeMembers(t) case t.objectFlags&ObjectFlagsAnonymous != 0: @@ -19527,68 +19557,164 @@ func (c *Checker) resolveStructuredTypeMembers(t *Type) *StructuredType { return t.AsStructuredType() } -func (c *Checker) resolveClassOrInterfaceMembers(t *Type) { - c.resolveObjectTypeMembers(t, t, nil, nil) -} - -func (c *Checker) resolveTypeReferenceMembers(t *Type) { - source := t.Target() - typeParameters := source.AsInterfaceType().allTypeParameters - typeArguments := c.getTypeArguments(t) - paddedTypeArguments := typeArguments - if len(typeArguments) == len(typeParameters)-1 { - paddedTypeArguments = core.Concatenate(typeArguments, []*Type{t}) - } - c.resolveObjectTypeMembers(t, source, typeParameters, paddedTypeArguments) -} - -func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters []*Type, typeArguments []*Type) { +func (c *Checker) resolveObjectTypeMembers(t *Type) { var mapper *TypeMapper + var typeParameters []*Type + var typeArguments []*Type var members ast.SymbolTable var callSignatures []*Signature var constructSignatures []*Signature var indexInfos []*IndexInfo - var instantiated bool + source := c.getTargetType(t) + if t.objectFlags&ObjectFlagsReference != 0 { + typeParameters = source.AsInterfaceType().allTypeParameters + typeArguments = c.getTypeArguments(t) + if len(typeArguments) == len(typeParameters)-1 { + typeArguments = core.Concatenate(typeArguments, []*Type{t}) + } + } resolved := c.resolveDeclaredMembers(source) if slices.Equal(typeParameters, typeArguments) { - members = resolved.declaredMembers callSignatures = resolved.declaredCallSignatures constructSignatures = resolved.declaredConstructSignatures indexInfos = resolved.declaredIndexInfos } else { - instantiated = true mapper = newTypeMapper(typeParameters, typeArguments) - members = c.instantiateSymbolTable(resolved.declaredMembers, mapper) callSignatures = c.instantiateSignatures(resolved.declaredCallSignatures, mapper) constructSignatures = c.instantiateSignatures(resolved.declaredConstructSignatures, mapper) indexInfos = c.instantiateIndexInfos(resolved.declaredIndexInfos, mapper) } baseTypes := c.getBaseTypes(source) - if len(baseTypes) != 0 { - if !instantiated { - members = maps.Clone(members) + instantiatedBaseTypes := baseTypes + thisArgument := core.LastOrNil(typeArguments) + if len(baseTypes) != 0 && thisArgument != nil { + instantiatedBaseTypes = make([]*Type, len(baseTypes)) + for i, baseType := range baseTypes { + instantiatedBaseTypes[i] = c.getTypeWithThisArgument(c.instantiateType(baseType, mapper), thisArgument, false /*needsApparentType*/) + } + } + // Member layout must be computed before inherited signatures, which may circularly depend on it + layout := c.getMemberLayout(t, instantiatedBaseTypes) + for _, instantiatedBaseType := range instantiatedBaseTypes { + callSignatures = core.Concatenate(callSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindCall)) + constructSignatures = core.Concatenate(constructSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindConstruct)) + var inheritedIndexInfos []*IndexInfo + if instantiatedBaseType != c.anyType { + inheritedIndexInfos = c.getIndexInfosOfType(instantiatedBaseType) + } else { + inheritedIndexInfos = []*IndexInfo{c.anyBaseTypeIndexInfo} } - thisArgument := core.LastOrNil(typeArguments) - for _, baseType := range baseTypes { - instantiatedBaseType := baseType - if thisArgument != nil { - instantiatedBaseType = c.getTypeWithThisArgument(c.instantiateType(baseType, mapper), thisArgument, false /*needsApparentType*/) - } - members = c.addInheritedMembers(members, c.getPropertiesOfType(instantiatedBaseType)) - callSignatures = core.Concatenate(callSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindCall)) - constructSignatures = core.Concatenate(constructSignatures, c.getSignaturesOfType(instantiatedBaseType, SignatureKindConstruct)) - var inheritedIndexInfos []*IndexInfo - if instantiatedBaseType != c.anyType { - inheritedIndexInfos = c.getIndexInfosOfType(instantiatedBaseType) - } else { - inheritedIndexInfos = []*IndexInfo{c.anyBaseTypeIndexInfo} + indexInfos = core.Concatenate(indexInfos, core.Filter(inheritedIndexInfos, func(info *IndexInfo) bool { + return findIndexInfo(indexInfos, info.keyType) == nil + })) + } + c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) + lazyState := c.lazyStateArena.New() + lazyState.layout = layout + lazyState.mapper = mapper + lazyState.baseTypes = instantiatedBaseTypes + t.AsTypeReference().lazy = lazyState +} + +func (c *Checker) getMemberLayout(t *Type, baseTypes []*Type) *MemberLayout { + if t.objectFlags&ObjectFlagsReference == 0 { + return c.createMemberLayout(t, baseTypes) + } + source := c.getTargetType(t) + key := c.getMemberLayoutKey(source, baseTypes) + layout := c.memberLayoutCache[key] + if layout == nil { + layout = c.createMemberLayout(source, baseTypes) + if c.memberLayoutCache == nil { + c.memberLayoutCache = make(map[CacheHashKey]*MemberLayout) + } + c.memberLayoutCache[key] = layout + } + return layout +} + +func (c *Checker) getMemberLayoutKey(t *Type, baseTypes []*Type) CacheHashKey { + var b keyBuilder + b.reserve(20 + 5*len(baseTypes)) + b.writeType(t) + // Late binding may add new declared members, so include the declared member count in the key + b.writeInt(len(t.AsInterfaceType().declaredMembers)) + b.writeInt(len(baseTypes)) + for _, baseType := range baseTypes { + if baseType.objectFlags&ObjectFlagsReference != 0 { + c.resolveStructuredTypeMembers(baseType) + b.writeByte('+') + b.writeUint32(baseType.AsTypeReference().lazy.layout.id) + } else { + b.writeByte('-') + b.writeType(baseType) + } + } + return b.hash() +} + +func (c *Checker) createMemberLayout(t *Type, baseTypes []*Type) *MemberLayout { + // Reuse c.layoutMemberInfos to avoid repeated allocations + layoutMemberInfos := c.layoutMemberInfos + c.layoutMemberInfos = nil + addMember := func(symbol *ast.Symbol, baseIndex int) { + if _, ok := layoutMemberInfos[symbol.Name()]; !ok { + if layoutMemberInfos == nil { + layoutMemberInfos = make(map[string]MemberInfo) } - indexInfos = core.Concatenate(indexInfos, core.Filter(inheritedIndexInfos, func(info *IndexInfo) bool { - return findIndexInfo(indexInfos, info.keyType) == nil - })) + layoutMemberInfos[symbol.Name()] = MemberInfo{symbol: symbol, baseIndex: int32(baseIndex)} } } - c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos) + // Add declared members + for id, symbol := range t.AsInterfaceType().declaredMembers { + if c.isNamedMember(symbol, id) { + addMember(symbol, -1) + } + } + // Add inherited members + for baseIndex, baseType := range baseTypes { + if baseType.objectFlags&(ObjectFlagsReference|ObjectFlagsClassOrInterface) != 0 { + c.resolveStructuredTypeMembers(baseType) + for _, info := range baseType.AsTypeReference().lazy.layout.memberInfos { + if !isStaticPrivateIdentifierProperty(info.symbol) { + addMember(info.symbol, baseIndex) + } + } + } else { + for _, symbol := range c.getPropertiesOfType(baseType) { + if !isStaticPrivateIdentifierProperty(symbol) { + addMember(symbol, baseIndex) + } + } + } + } + memberInfos := slices.AppendSeq(make([]MemberInfo, 0, len(layoutMemberInfos)), maps.Values(layoutMemberInfos)) + clear(layoutMemberInfos) + c.layoutMemberInfos = layoutMemberInfos + // Sort by symbols, but put declared members (baseIndex < 0) first + slices.SortFunc(memberInfos, func(a, b MemberInfo) int { + if a.baseIndex < 0 && b.baseIndex >= 0 { + return -1 + } + if a.baseIndex >= 0 && b.baseIndex < 0 { + return 1 + } + return c.CompareSymbols(a.symbol, b.symbol) + }) + // Store slot indices in the sorted memberInfos and build the memberInfoMap. Slot indices are used to + // identify slots in the instantiated type's properties list. + memberInfoMap := make(map[string]*MemberInfo, len(memberInfos)) + for i := range memberInfos { + memberInfo := &memberInfos[i] + memberInfo.slotIndex = int32(i) + memberInfoMap[memberInfo.symbol.Name()] = memberInfo + } + layout := c.memberLayoutArena.New() + layout.id = c.memberLayoutCount + layout.memberInfoMap = memberInfoMap + layout.memberInfos = memberInfos + c.memberLayoutCount++ + return layout } func findIndexInfo(indexInfos []*IndexInfo, keyType *Type) *IndexInfo { @@ -19789,7 +19915,7 @@ func (c *Checker) getSingleCallOrConstructSignature(t *Type) *Signature { func (c *Checker) getSingleSignature(t *Type, kind SignatureKind, allowMembers bool) *Signature { if t.flags&TypeFlagsObject != 0 { resolved := c.resolveStructuredTypeMembers(t) - if allowMembers || len(resolved.properties) == 0 && len(resolved.getIndexInfos()) == 0 { + if allowMembers || !resolved.hasProperties() && len(resolved.getIndexInfos()) == 0 { if kind == SignatureKindCall && len(resolved.CallSignatures()) == 1 && len(resolved.ConstructSignatures()) == 0 { return resolved.CallSignatures()[0] } @@ -21136,7 +21262,7 @@ func (c *Checker) resolveAnonymousTypeMembers(t *Type) { if baseConstructorIndexInfo != nil { indexInfos = append(indexInfos, baseConstructorIndexInfo) } - if symbol.Flags()&ast.SymbolFlagsEnum != 0 && (c.getDeclaredTypeOfSymbol(symbol).flags&TypeFlagsEnum != 0 || core.Some(d.properties, func(prop *ast.Symbol) bool { + if symbol.Flags()&ast.SymbolFlagsEnum != 0 && (c.getDeclaredTypeOfSymbol(symbol).flags&TypeFlagsEnum != 0 || core.Some(d.getProperties(), func(prop *ast.Symbol) bool { return c.getTypeOfSymbol(prop).flags&TypeFlagsNumberLike != 0 })) { indexInfos = append(indexInfos, c.enumNumberIndexInfo) @@ -21196,11 +21322,11 @@ func (c *Checker) instantiateSymbolTable(symbols ast.SymbolTable, m *TypeMapper) } func (c *Checker) instantiateSymbol(symbol *ast.Symbol, m *TypeMapper) *ast.Symbol { - if symbol == nil { - return nil + if symbol == nil || m == nil { + return symbol } links := c.valueSymbolLinks.Get(symbol) - if m != nil && m.MapsThisOnly() && isThisless(symbol) { + if m.MapsThisOnly() && isThisless(symbol) { return symbol } // If the type of the symbol is already resolved, and if that type could not possibly @@ -21844,7 +21970,7 @@ func (c *Checker) includeMixinType(t *Type, types []*Type, mixinFlags []bool, in func (c *Checker) getPropertyOfObjectType(t *Type, name string) *ast.Symbol { if t.flags&TypeFlagsObject != 0 { resolved := c.resolveStructuredTypeMembers(t) - symbol := resolved.members[name] + symbol := resolved.getMember(name) if symbol != nil && c.symbolIsValue(symbol) { return symbol } @@ -22322,7 +22448,7 @@ func (c *Checker) somePropertyReducesToNever(t *Type) bool { counts := c.getTemporaryPropertyCounts() defer c.releaseTemporaryPropertyCounts(counts) for _, t := range t.Types() { - for _, prop := range c.getPropertiesOfType(t) { + for _, prop := range c.getLayoutPropertiesOfType(t) { counts.Set(prop.Name(), counts.GetOrZero(prop.Name())+1) } } @@ -27080,7 +27206,7 @@ func (c *Checker) IsEmptyAnonymousObjectType(t *Type) bool { } func (c *Checker) isEmptyResolvedType(t *StructuredType) bool { - return t.AsType() != c.anyFunctionType && len(t.properties) == 0 && len(t.getSignatures()) == 0 && len(t.getIndexInfos()) == 0 + return t.AsType() != c.anyFunctionType && !t.hasProperties() && len(t.getSignatures()) == 0 && len(t.getIndexInfos()) == 0 } func (c *Checker) isEmptyObjectType(t *Type) bool { @@ -27328,7 +27454,7 @@ func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, inclu if includeOrigin && t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0 || t.alias != nil { origin = c.newIndexType(t, IndexFlagsNone) } - props := c.getPropertiesOfType(t) + props := c.getLayoutPropertiesOfType(t) indexInfos := c.getIndexInfosOfType(t) types := make([]*Type, 0, len(props)+len(indexInfos)) for _, prop := range props { @@ -27741,7 +27867,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy c.addDiagnostic(createDiagnosticForNode(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1, indexType.AsLiteralType().value, c.TypeToString(objectType))) return c.undefinedType } else if indexType.flags&(TypeFlagsNumber|TypeFlagsString) != 0 { - types := core.Map(objectType.AsStructuredType().properties, func(prop *ast.Symbol) *Type { + types := core.Map(objectType.AsStructuredType().getProperties(), func(prop *ast.Symbol) *Type { return c.getTypeOfSymbol(prop) }) return c.getUnionType(append(types, c.undefinedType)) @@ -27968,7 +28094,7 @@ func (c *Checker) getPropertyNameFromIndex(indexType *Type, accessNode *ast.Node } func (c *Checker) isStringIndexSignatureOnlyTypeWorker(t *Type) bool { - return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.getPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || + return t.flags&TypeFlagsObject != 0 && !c.isGenericMappedType(t) && len(c.getLayoutPropertiesOfType(t)) == 0 && len(c.getIndexInfosOfType(t)) == 1 && c.getIndexInfoOfType(t, c.stringType) != nil || t.flags&TypeFlagsUnionOrIntersection != 0 && core.Every(t.Types(), c.isStringIndexSignatureOnlyType) } @@ -31416,7 +31542,7 @@ func (c *Checker) discriminateContextualTypeByObjectMembers(node *ast.Node, cont } return false }) - discriminantMembers := core.Filter(c.getPropertiesOfType(contextualType), func(s *ast.Symbol) bool { + discriminantMembers := core.Filter(c.getLayoutPropertiesOfType(contextualType), func(s *ast.Symbol) bool { return s.Flags()&ast.SymbolFlagsOptional != 0 && node.Symbol().Members()[s.Name()] == nil && c.isDiscriminantProperty(contextualType, s.Name()) }) discriminator := &ObjectLiteralDiscriminator{c: c, props: discriminantProperties, members: discriminantMembers} @@ -31788,7 +31914,7 @@ func (c *Checker) isFunctionObjectType(t *Type) bool { // We do a quick check for a "bind" property before performing the more expensive subtype // check. This gives us a quicker out in the common case where an object type is not a function. resolved := c.resolveStructuredTypeMembers(t) - return len(resolved.getSignatures()) != 0 || resolved.members["bind"] != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) + return len(resolved.getSignatures()) != 0 || resolved.getMember("bind") != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) } func (c *Checker) getTypeWithFacts(t *Type, include TypeFacts) *Type { @@ -32284,7 +32410,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy // member should more exactly be the kind of (declarationless) symbol we want. // (See #44364 and #45031 for relevant implementation PRs) if metaProp.KeywordToken == ast.KindImportKeyword && node.Text() == "meta" { - return c.getGlobalImportMetaExpressionType().AsObjectType().members["meta"] + return c.getGlobalImportMetaExpressionType().AsObjectType().getMember("meta") } // no other meta properties are valid syntax, thus no others should have symbols return nil diff --git a/tsc/internal/checker/nodebuilder_hover.go b/tsc/internal/checker/nodebuilder_hover.go index b048c5d1618c6..7bf066a03485f 100644 --- a/tsc/internal/checker/nodebuilder_hover.go +++ b/tsc/internal/checker/nodebuilder_hover.go @@ -263,7 +263,7 @@ func (b *NodeBuilderImpl) expandInterfaceDecl(symbol *ast.Symbol) *ast.Node { members = append(members, b.signatureToSignatureDeclarationHelper(sig, ast.KindCallSignature, nil)) } // Properties, filtering inherited - filteredProps := b.filterInheritedProperties(interfaceType, baseTypes, resolved.properties) + filteredProps := b.filterInheritedProperties(interfaceType, baseTypes, resolved.getProperties()) members = b.serializePropertiesWithTruncation(filteredProps, members) // Heritage clauses diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 3d84ff3bd4094..45f8ddc00dcf2 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -576,7 +576,7 @@ func (b *NodeBuilderImpl) getResolvedTypeWithoutAbstractConstructSignatures(t *S t.extra.objectTypeWithoutAbstractConstructSignatures = t.AsType() return t.AsType() } - typeCopy := b.ch.newAnonymousType(t.symbol, t.members, t.CallSignatures(), core.IfElse(len(constructSignatures) > 0, constructSignatures, []*Signature{}), t.getIndexInfos()) + typeCopy := b.ch.newAnonymousType(t.symbol, t.getMembers(), t.CallSignatures(), core.IfElse(len(constructSignatures) > 0, constructSignatures, []*Signature{}), t.getIndexInfos()) t.extra.objectTypeWithoutAbstractConstructSignatures = typeCopy typeCopy.AsStructuredType().ensureExtra().objectTypeWithoutAbstractConstructSignatures = typeCopy return typeCopy @@ -2758,7 +2758,7 @@ func (b *NodeBuilderImpl) createTypeNodesFromResolvedType(resolvedType *Structur typeElements = slices.Concat(typeElements, b.indexInfoToObjectComputedNamesOrSignatureDeclaration(info, typeNode)) } - properties := resolvedType.properties + properties := resolvedType.getProperties() if len(properties) == 0 { return b.f.NewNodeList(typeElements) } @@ -2807,7 +2807,7 @@ func (b *NodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode { resolved := b.ch.resolveStructuredTypeMembers(t) callSigs := resolved.CallSignatures() ctorSigs := resolved.ConstructSignatures() - if len(resolved.properties) == 0 && len(resolved.getIndexInfos()) == 0 { + if len(resolved.getProperties()) == 0 && len(resolved.getIndexInfos()) == 0 { if len(callSigs) == 0 && len(ctorSigs) == 0 { b.ctx.approximateLength += 2 result := b.f.NewTypeLiteralNode(b.f.NewNodeList([]*ast.Node{})) @@ -2836,9 +2836,9 @@ func (b *NodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode { return b.ch.getOrCreateTypeFromSignature(s) }) // count the number of type elements excluding abstract constructors - typeElementCount := len(callSigs) + (len(ctorSigs) - len(abstractSignatures)) + len(resolved.getIndexInfos()) + core.IfElse(b.ctx.flags&nodebuilder.FlagsWriteClassExpressionAsTypeLiteral != 0, core.CountWhere(resolved.properties, func(p *ast.Symbol) bool { + typeElementCount := len(callSigs) + (len(ctorSigs) - len(abstractSignatures)) + len(resolved.getIndexInfos()) + core.IfElse(b.ctx.flags&nodebuilder.FlagsWriteClassExpressionAsTypeLiteral != 0, core.CountWhere(resolved.getProperties(), func(p *ast.Symbol) bool { return p.Flags()&ast.SymbolFlagsPrototype == 0 - }), len(resolved.properties)) + }), len(resolved.getProperties())) // don't include an empty object literal if there were no other static-side // properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}` // and not `(abstract new () => {}) & {}` diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index d3b6c86014498..007fba2511a13 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -679,7 +679,7 @@ func (c *Checker) elaborateArrowFunction(node *ast.Node, source *Type, target *T func (c *Checker) isWeakType(t *Type) bool { if t.flags&TypeFlagsObject != 0 { resolved := c.resolveStructuredTypeMembers(t) - return len(resolved.getSignatures()) == 0 && len(resolved.getIndexInfos()) == 0 && len(resolved.properties) > 0 && core.Every(resolved.properties, func(p *ast.Symbol) bool { + return len(resolved.getSignatures()) == 0 && len(resolved.getIndexInfos()) == 0 && len(c.getLayoutPropertiesOfType(t)) > 0 && core.Every(c.getLayoutPropertiesOfType(t), func(p *ast.Symbol) bool { return p.Flags()&ast.SymbolFlagsOptional != 0 }) } @@ -975,14 +975,16 @@ func (c *Checker) getUnmatchedProperties(source *Type, target *Type, requireOpti } func (c *Checker) getUnmatchedPropertiesWorker(source *Type, target *Type, requireOptionalProperties bool, matchDiscriminantProperties bool, propsOut *[]*ast.Symbol) *ast.Symbol { - properties := c.getPropertiesOfType(target) - for _, targetProp := range properties { + for _, targetProp := range c.getLayoutPropertiesOfType(target) { // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass if isStaticPrivateIdentifierProperty(targetProp) { continue } if requireOptionalProperties || targetProp.Flags()&ast.SymbolFlagsOptional == 0 && targetProp.CheckFlags()&ast.CheckFlagsPartial == 0 { sourceProp := c.getPropertyOfType(source, targetProp.Name()) + if sourceProp == nil || matchDiscriminantProperties { + targetProp = c.getPropertyOfType(target, targetProp.Name()) + } if sourceProp == nil { if propsOut == nil { return targetProp diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index 90f3f2f901844..b20d1798e89be 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -154,7 +154,7 @@ func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb if reducedType.flags&TypeFlagsStructuredType == 0 { return } - for name, symbol := range c.resolveStructuredTypeMembers(reducedType).members { + for name, symbol := range c.resolveStructuredTypeMembers(reducedType).getMembers() { if c.isNamedMember(symbol, name) { cb(symbol, name) } diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index a3cfe28c2e735..f119288a21744 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -1143,6 +1143,82 @@ func (t *StructuredType) ConstructSignatures() []*Signature { return slices.Clip(t.extra.signatures[t.extra.callSignatureCount:]) } +func (t *StructuredType) getMember(name string) *ast.Symbol { + if t.members != nil { + return t.members[name] + } + lazy := t.getLazyState() + if lazy == nil { + return nil + } + memberInfo := lazy.layout.memberInfoMap[name] + if memberInfo == nil { + return nil + } + return t.getPropertyAt(int(memberInfo.slotIndex)) +} + +func (t *StructuredType) getMembers() ast.SymbolTable { + if t.members == nil { + if properties := t.getProperties(); len(properties) != 0 { + t.members = make(ast.SymbolTable, len(properties)) + for _, member := range properties { + t.members[member.Name()] = member + } + } + } + return t.members +} + +func (t *StructuredType) getPropertyAt(index int) *ast.Symbol { + lazy := t.getLazyState() + if lazy == nil { + return t.properties[index] + } + if t.properties == nil { + t.properties = make([]*ast.Symbol, len(lazy.layout.memberInfos)) + } + member := t.properties[index] + if member == nil { + memberInfo := lazy.layout.memberInfos[index] + if memberInfo.baseIndex < 0 { + member = t.checker.instantiateSymbol(memberInfo.symbol, lazy.mapper) + } else { + member = t.checker.getPropertyOfType(lazy.baseTypes[memberInfo.baseIndex], memberInfo.symbol.Name()) + } + t.properties[index] = member + } + return member +} + +func (t *StructuredType) getProperties() []*ast.Symbol { + if lazy := t.getLazyState(); lazy != nil && !lazy.propertiesResolved { + for i := range lazy.layout.memberInfos { + t.getPropertyAt(i) + } + lazy.propertiesResolved = true + } + return t.AsStructuredType().properties +} + +func (t *StructuredType) hasProperties() bool { + if len(t.properties) != 0 { + return true + } + lazy := t.getLazyState() + if lazy == nil { + return false + } + return len(lazy.layout.memberInfos) != 0 +} + +func (t *StructuredType) getLazyState() *LazyState { + if t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0 { + return t.AsType().AsTypeReference().lazy + } + return nil +} + func (t *StructuredType) getSignatures() []*Signature { if t.extra == nil { return nil @@ -1165,7 +1241,7 @@ func (t *StructuredType) ensureExtra() *structuredTypeExtra { } func (t *StructuredType) Properties() []*ast.Symbol { - return t.properties + return t.getProperties() } // Except for tuple type references and reverse mapped types, all object types have an associated symbol. @@ -1216,6 +1292,27 @@ type TypeReference struct { ObjectType node *ast.Node // TypeReferenceNode | ArrayTypeNode | TupleTypeNode when deferred, else nil resolvedTypeArguments []*Type + lazy *LazyState // Resolved member layout and instantiation state +} + +type LazyState struct { + layout *MemberLayout + mapper *TypeMapper + baseTypes []*Type + propertiesResolved bool +} + +type MemberLayout struct { + id uint32 // Unique identifier for the member layout + memberInfoMap map[string]*MemberInfo // MemberInfos keyed by property name + memberInfos []MemberInfo // MemberInfos in sorted order + layoutProperties []*ast.Symbol // Lazily created list of layout properties (symbols corresponding to memberInfos) +} + +type MemberInfo struct { + symbol *ast.Symbol // Uninstantiated symbol + baseIndex int32 // Index of base type with symbol, or -1 if locally declared + slotIndex int32 // Index of resolved symbol in members array } func (t *TypeReference) AsTypeReference() *TypeReference { return t } diff --git a/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.js b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.js new file mode 100644 index 0000000000000..f74a9a2dcb804 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.js @@ -0,0 +1,52 @@ +//// [tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts] //// + +//// [lateBoundMemberLayoutReentrancy.ts] +declare const rI: RI<"a">; +rI.x +interface RI { + x: T; + [rI.x]: "b"; +} +declare const rI2: RI<"b">; +export const v1 = rI2.a; +export const v2 = rI.a; +export type K2 = keyof RI<"b">; +export const k: K2 = "a"; +export const o: RI<"b"> = { x: "b", a: "b" }; + +declare const rC: RC<"a">; +rC.x +declare class RC { + x: T; + [rC.x]: "b"; +} +declare const rC2: RC<"b">; +export const w1 = rC2.a; +export const w2 = rC.a; + + +//// [lateBoundMemberLayoutReentrancy.js] +rI.x; +export const v1 = rI2.a; +export const v2 = rI.a; +export const k = "a"; +export const o = { x: "b", a: "b" }; +rC.x; +export const w1 = rC2.a; +export const w2 = rC.a; + + +//// [lateBoundMemberLayoutReentrancy.d.ts] +declare const rI: RI<"a">; +interface RI { + x: T; + [rI.x]: "b"; +} +export declare const v1: "b"; +export declare const v2: "b"; +export type K2 = keyof RI<"b">; +export declare const k: K2; +export declare const o: RI<"b">; +export declare const w1: "b"; +export declare const w2: "b"; +export {}; diff --git a/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.symbols b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.symbols new file mode 100644 index 0000000000000..5bdce11469134 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.symbols @@ -0,0 +1,95 @@ +//// [tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts] //// + +=== lateBoundMemberLayoutReentrancy.ts === +declare const rI: RI<"a">; +>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13)) +>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4)) + +rI.x +>rI.x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35)) +>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13)) +>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35)) + +interface RI { +>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4)) +>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 13)) + + x: T; +>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35)) +>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 13)) + + [rI.x]: "b"; +>[rI.x] : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9)) +>rI.x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35)) +>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13)) +>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35)) +} +declare const rI2: RI<"b">; +>rI2 : Symbol(rI2, Decl(lateBoundMemberLayoutReentrancy.ts, 6, 13)) +>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4)) + +export const v1 = rI2.a; +>v1 : Symbol(v1, Decl(lateBoundMemberLayoutReentrancy.ts, 7, 12)) +>rI2.a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9)) +>rI2 : Symbol(rI2, Decl(lateBoundMemberLayoutReentrancy.ts, 6, 13)) +>a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9)) + +export const v2 = rI.a; +>v2 : Symbol(v2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 12)) +>rI.a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9)) +>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13)) +>a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9)) + +export type K2 = keyof RI<"b">; +>K2 : Symbol(K2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 23)) +>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4)) + +export const k: K2 = "a"; +>k : Symbol(k, Decl(lateBoundMemberLayoutReentrancy.ts, 10, 12)) +>K2 : Symbol(K2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 23)) + +export const o: RI<"b"> = { x: "b", a: "b" }; +>o : Symbol(o, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 12)) +>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4)) +>x : Symbol(x, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 27)) +>a : Symbol(a, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 35)) + +declare const rC: RC<"a">; +>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13)) +>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4)) + +rC.x +>rC.x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39)) +>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13)) +>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39)) + +declare class RC { +>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4)) +>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 17)) + + x: T; +>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39)) +>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 17)) + + [rC.x]: "b"; +>[rC.x] : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9)) +>rC.x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39)) +>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13)) +>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39)) +} +declare const rC2: RC<"b">; +>rC2 : Symbol(rC2, Decl(lateBoundMemberLayoutReentrancy.ts, 19, 13)) +>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4)) + +export const w1 = rC2.a; +>w1 : Symbol(w1, Decl(lateBoundMemberLayoutReentrancy.ts, 20, 12)) +>rC2.a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9)) +>rC2 : Symbol(rC2, Decl(lateBoundMemberLayoutReentrancy.ts, 19, 13)) +>a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9)) + +export const w2 = rC.a; +>w2 : Symbol(w2, Decl(lateBoundMemberLayoutReentrancy.ts, 21, 12)) +>rC.a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9)) +>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13)) +>a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9)) + diff --git a/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.types b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.types new file mode 100644 index 0000000000000..08b081ddf6850 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/lateBoundMemberLayoutReentrancy.types @@ -0,0 +1,86 @@ +//// [tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts] //// + +=== lateBoundMemberLayoutReentrancy.ts === +declare const rI: RI<"a">; +>rI : RI<"a"> + +rI.x +>rI.x : "a" +>rI : RI<"a"> +>x : "a" + +interface RI { + x: T; +>x : T + + [rI.x]: "b"; +>[rI.x] : "b" +>rI.x : "a" +>rI : RI<"a"> +>x : "a" +} +declare const rI2: RI<"b">; +>rI2 : RI<"b"> + +export const v1 = rI2.a; +>v1 : "b" +>rI2.a : "b" +>rI2 : RI<"b"> +>a : "b" + +export const v2 = rI.a; +>v2 : "b" +>rI.a : "b" +>rI : RI<"a"> +>a : "b" + +export type K2 = keyof RI<"b">; +>K2 : keyof RI<"b"> + +export const k: K2 = "a"; +>k : keyof RI<"b"> +>"a" : "a" + +export const o: RI<"b"> = { x: "b", a: "b" }; +>o : RI<"b"> +>{ x: "b", a: "b" } : { x: "b"; a: "b"; } +>x : "b" +>"b" : "b" +>a : "b" +>"b" : "b" + +declare const rC: RC<"a">; +>rC : RC<"a"> + +rC.x +>rC.x : "a" +>rC : RC<"a"> +>x : "a" + +declare class RC { +>RC : RC + + x: T; +>x : T + + [rC.x]: "b"; +>[rC.x] : "b" +>rC.x : "a" +>rC : RC<"a"> +>x : "a" +} +declare const rC2: RC<"b">; +>rC2 : RC<"b"> + +export const w1 = rC2.a; +>w1 : "b" +>rC2.a : "b" +>rC2 : RC<"b"> +>a : "b" + +export const w2 = rC.a; +>w2 : "b" +>rC.a : "b" +>rC : RC<"a"> +>a : "b" + diff --git a/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.symbols b/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.symbols new file mode 100644 index 0000000000000..abe1b21713175 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.symbols @@ -0,0 +1,146 @@ +//// [tests/cases/compiler/lazyInheritedMemberLookup.ts] //// + +=== lazyInheritedMemberLookup.ts === +// Inherited members are looked up individually before the members of each type are enumerated. + +interface Grand { +>Grand : Symbol(Grand, Decl(lazyInheritedMemberLookup.ts, 0, 0)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 2, 16)) + + grand: T; +>grand : Symbol(Grand.grand, Decl(lazyInheritedMemberLookup.ts, 2, 20)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 2, 16)) + + shared: T; +>shared : Symbol(Grand.shared, Decl(lazyInheritedMemberLookup.ts, 3, 13)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 2, 16)) +} +type Mixin = { mixin: T }; +>Mixin : Symbol(Mixin, Decl(lazyInheritedMemberLookup.ts, 5, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 6, 11)) +>mixin : Symbol(mixin, Decl(lazyInheritedMemberLookup.ts, 6, 17)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 6, 11)) + +type Fixed = { fixed: string }; +>Fixed : Symbol(Fixed, Decl(lazyInheritedMemberLookup.ts, 6, 29)) +>fixed : Symbol(fixed, Decl(lazyInheritedMemberLookup.ts, 7, 14)) + +interface Base extends Grand { +>Base : Symbol(Base, Decl(lazyInheritedMemberLookup.ts, 7, 31)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 8, 15)) +>Grand : Symbol(Grand, Decl(lazyInheritedMemberLookup.ts, 0, 0)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 8, 15)) + + base: T; +>base : Symbol(Base.base, Decl(lazyInheritedMemberLookup.ts, 8, 38)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 8, 15)) +} +interface Derived extends Base, Mixin, Fixed { +>Derived : Symbol(Derived, Decl(lazyInheritedMemberLookup.ts, 10, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 11, 18)) +>Base : Symbol(Base, Decl(lazyInheritedMemberLookup.ts, 7, 31)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 11, 18)) +>Mixin : Symbol(Mixin, Decl(lazyInheritedMemberLookup.ts, 5, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 11, 18)) +>Fixed : Symbol(Fixed, Decl(lazyInheritedMemberLookup.ts, 6, 29)) + + shared: T[]; +>shared : Symbol(Derived.shared, Decl(lazyInheritedMemberLookup.ts, 11, 55)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 11, 18)) + + derived: T; +>derived : Symbol(Derived.derived, Decl(lazyInheritedMemberLookup.ts, 12, 16)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 11, 18)) +} +class C { +>C : Symbol(C, Decl(lazyInheritedMemberLookup.ts, 14, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 15, 8)) + + declared!: T; +>declared : Symbol(C.declared, Decl(lazyInheritedMemberLookup.ts, 15, 12)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 15, 8)) +} +class D extends C implements Derived { +>D : Symbol(D, Decl(lazyInheritedMemberLookup.ts, 17, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) +>C : Symbol(C, Decl(lazyInheritedMemberLookup.ts, 14, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) +>Derived : Symbol(Derived, Decl(lazyInheritedMemberLookup.ts, 10, 1)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) + + grand!: T[]; +>grand : Symbol(D.grand, Decl(lazyInheritedMemberLookup.ts, 18, 49)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) + + shared!: T[]; +>shared : Symbol(D.shared, Decl(lazyInheritedMemberLookup.ts, 19, 16)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) + + mixin!: T; +>mixin : Symbol(D.mixin, Decl(lazyInheritedMemberLookup.ts, 20, 17)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) + + fixed!: string; +>fixed : Symbol(D.fixed, Decl(lazyInheritedMemberLookup.ts, 21, 14)) + + base!: T; +>base : Symbol(D.base, Decl(lazyInheritedMemberLookup.ts, 22, 19)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) + + derived!: T; +>derived : Symbol(D.derived, Decl(lazyInheritedMemberLookup.ts, 23, 13)) +>T : Symbol(T, Decl(lazyInheritedMemberLookup.ts, 18, 8)) +} + +declare const d: Derived; +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) +>Derived : Symbol(Derived, Decl(lazyInheritedMemberLookup.ts, 10, 1)) + +const grand = d.grand; +>grand : Symbol(grand, Decl(lazyInheritedMemberLookup.ts, 28, 5)) +>d.grand : Symbol(Grand.grand, Decl(lazyInheritedMemberLookup.ts, 2, 20)) +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) +>grand : Symbol(Grand.grand, Decl(lazyInheritedMemberLookup.ts, 2, 20)) + +const mixin = d.mixin; +>mixin : Symbol(mixin, Decl(lazyInheritedMemberLookup.ts, 29, 5)) +>d.mixin : Symbol(mixin, Decl(lazyInheritedMemberLookup.ts, 6, 17)) +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) +>mixin : Symbol(mixin, Decl(lazyInheritedMemberLookup.ts, 6, 17)) + +const fixed = d.fixed; +>fixed : Symbol(fixed, Decl(lazyInheritedMemberLookup.ts, 30, 5)) +>d.fixed : Symbol(fixed, Decl(lazyInheritedMemberLookup.ts, 7, 14)) +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) +>fixed : Symbol(fixed, Decl(lazyInheritedMemberLookup.ts, 7, 14)) + +const shared = d.shared; +>shared : Symbol(shared, Decl(lazyInheritedMemberLookup.ts, 31, 5)) +>d.shared : Symbol(Derived.shared, Decl(lazyInheritedMemberLookup.ts, 11, 55)) +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) +>shared : Symbol(Derived.shared, Decl(lazyInheritedMemberLookup.ts, 11, 55)) + +const all = { ...d }; +>all : Symbol(all, Decl(lazyInheritedMemberLookup.ts, 32, 5)) +>d : Symbol(d, Decl(lazyInheritedMemberLookup.ts, 27, 13)) + +declare const keys: { [K in keyof Derived]: K }; +>keys : Symbol(keys, Decl(lazyInheritedMemberLookup.ts, 33, 13)) +>K : Symbol(K, Decl(lazyInheritedMemberLookup.ts, 33, 23)) +>Derived : Symbol(Derived, Decl(lazyInheritedMemberLookup.ts, 10, 1)) +>K : Symbol(K, Decl(lazyInheritedMemberLookup.ts, 33, 23)) + +declare const e: D; +>e : Symbol(e, Decl(lazyInheritedMemberLookup.ts, 35, 13)) +>D : Symbol(D, Decl(lazyInheritedMemberLookup.ts, 17, 1)) + +const declared = e.declared; +>declared : Symbol(declared, Decl(lazyInheritedMemberLookup.ts, 36, 5)) +>e.declared : Symbol(C.declared, Decl(lazyInheritedMemberLookup.ts, 15, 12)) +>e : Symbol(e, Decl(lazyInheritedMemberLookup.ts, 35, 13)) +>declared : Symbol(C.declared, Decl(lazyInheritedMemberLookup.ts, 15, 12)) + +const allE = { ...e }; +>allE : Symbol(allE, Decl(lazyInheritedMemberLookup.ts, 37, 5)) +>e : Symbol(e, Decl(lazyInheritedMemberLookup.ts, 35, 13)) + diff --git a/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.types b/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.types new file mode 100644 index 0000000000000..54cf76203287b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/lazyInheritedMemberLookup.types @@ -0,0 +1,109 @@ +//// [tests/cases/compiler/lazyInheritedMemberLookup.ts] //// + +=== lazyInheritedMemberLookup.ts === +// Inherited members are looked up individually before the members of each type are enumerated. + +interface Grand { + grand: T; +>grand : T + + shared: T; +>shared : T +} +type Mixin = { mixin: T }; +>Mixin : Mixin +>mixin : T + +type Fixed = { fixed: string }; +>Fixed : Fixed +>fixed : string + +interface Base extends Grand { + base: T; +>base : T +} +interface Derived extends Base, Mixin, Fixed { + shared: T[]; +>shared : T[] + + derived: T; +>derived : T +} +class C { +>C : C + + declared!: T; +>declared : T +} +class D extends C implements Derived { +>D : D +>C : C + + grand!: T[]; +>grand : T[] + + shared!: T[]; +>shared : T[] + + mixin!: T; +>mixin : T + + fixed!: string; +>fixed : string + + base!: T; +>base : T + + derived!: T; +>derived : T +} + +declare const d: Derived; +>d : Derived + +const grand = d.grand; +>grand : number[] +>d.grand : number[] +>d : Derived +>grand : number[] + +const mixin = d.mixin; +>mixin : number +>d.mixin : number +>d : Derived +>mixin : number + +const fixed = d.fixed; +>fixed : string +>d.fixed : string +>d : Derived +>fixed : string + +const shared = d.shared; +>shared : number[] +>d.shared : number[] +>d : Derived +>shared : number[] + +const all = { ...d }; +>all : { grand: number[]; mixin: number; fixed: string; base: number; shared: number[]; derived: number; } +>{ ...d } : { grand: number[]; mixin: number; fixed: string; base: number; shared: number[]; derived: number; } +>d : Derived + +declare const keys: { [K in keyof Derived]: K }; +>keys : { grand: "grand"; mixin: "mixin"; fixed: "fixed"; base: "base"; shared: "shared"; derived: "derived"; } + +declare const e: D; +>e : D + +const declared = e.declared; +>declared : string[] +>e.declared : string[] +>e : D +>declared : string[] + +const allE = { ...e }; +>allE : { declared: string[]; grand: string[]; shared: string[]; mixin: string; fixed: string; base: string; derived: string; } +>{ ...e } : { declared: string[]; grand: string[]; shared: string[]; mixin: string; fixed: string; base: string; derived: string; } +>e : D + diff --git a/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).symbols b/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).symbols new file mode 100644 index 0000000000000..b68cf3b721b9d --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).symbols @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/namespaceImportOfCallableInterfaceExport.ts] //// + +=== mod.d.ts === +interface Base { +>Base : Symbol(Base, Decl(mod.d.ts, 0, 0)) +>T : Symbol(T, Decl(mod.d.ts, 0, 15)) + + value: T; +>value : Symbol(Base.value, Decl(mod.d.ts, 0, 19)) +>T : Symbol(T, Decl(mod.d.ts, 0, 15)) +} +interface Callable extends Base { +>Callable : Symbol(Callable, Decl(mod.d.ts, 2, 1)) +>Base : Symbol(Base, Decl(mod.d.ts, 0, 0)) + + (): void; + __esModule: true; +>__esModule : Symbol(Callable.__esModule, Decl(mod.d.ts, 4, 13)) + + other: number; +>other : Symbol(Callable.other, Decl(mod.d.ts, 5, 21)) +} +declare const callable: Callable; +>callable : Symbol(callable, Decl(mod.d.ts, 8, 13)) +>Callable : Symbol(Callable, Decl(mod.d.ts, 2, 1)) + +export = callable; +>callable : Symbol(callable, Decl(mod.d.ts, 8, 13)) + +=== main.ts === +import * as ns from "./mod"; +>ns : Symbol(ns, Decl(main.ts, 0, 6)) + +const value: string = ns.value; +>value : Symbol(value, Decl(main.ts, 1, 5)) +>ns.value : Symbol(Base.value, Decl(mod.d.ts, 0, 19)) +>ns : Symbol(ns, Decl(main.ts, 0, 6)) +>value : Symbol(Base.value, Decl(mod.d.ts, 0, 19)) + +const other: number = ns.other; +>other : Symbol(other, Decl(main.ts, 2, 5)) +>ns.other : Symbol(Callable.other, Decl(mod.d.ts, 5, 21)) +>ns : Symbol(ns, Decl(main.ts, 0, 6)) +>other : Symbol(Callable.other, Decl(mod.d.ts, 5, 21)) + diff --git a/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).types b/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).types new file mode 100644 index 0000000000000..c94785f4cd666 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/namespaceImportOfCallableInterfaceExport(esmoduleinterop=true).types @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/namespaceImportOfCallableInterfaceExport.ts] //// + +=== mod.d.ts === +interface Base { + value: T; +>value : T +} +interface Callable extends Base { + (): void; + __esModule: true; +>__esModule : true +>true : true + + other: number; +>other : number +} +declare const callable: Callable; +>callable : Callable + +export = callable; +>callable : Callable + +=== main.ts === +import * as ns from "./mod"; +>ns : { value: string; __esModule: true; other: number; } + +const value: string = ns.value; +>value : string +>ns.value : string +>ns : { value: string; __esModule: true; other: number; } +>value : string + +const other: number = ns.other; +>other : number +>ns.other : number +>ns : { value: string; __esModule: true; other: number; } +>other : number + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.symbols b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.symbols new file mode 100644 index 0000000000000..4d9ae1fa88d8c --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.symbols @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/sharedMemberLayoutGenericBase1.ts] //// + +=== sharedMemberLayoutGenericBase1.ts === +function factory(ctor: new () => T) { +>factory : Symbol(factory, Decl(sharedMemberLayoutGenericBase1.ts, 0, 0)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase1.ts, 0, 17)) +>ctor : Symbol(ctor, Decl(sharedMemberLayoutGenericBase1.ts, 0, 35)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase1.ts, 0, 17)) + + class Base extends ctor {} +>Base : Symbol(Base, Decl(sharedMemberLayoutGenericBase1.ts, 0, 55)) +>ctor : Symbol(ctor, Decl(sharedMemberLayoutGenericBase1.ts, 0, 35)) + + class Derived extends Base {} +>Derived : Symbol(Derived, Decl(sharedMemberLayoutGenericBase1.ts, 1, 30)) +>Base : Symbol(Base, Decl(sharedMemberLayoutGenericBase1.ts, 0, 55)) + + return Derived; +>Derived : Symbol(Derived, Decl(sharedMemberLayoutGenericBase1.ts, 1, 30)) +} + +class A { a = 1; } +>A : Symbol(A, Decl(sharedMemberLayoutGenericBase1.ts, 4, 1)) +>a : Symbol(A.a, Decl(sharedMemberLayoutGenericBase1.ts, 6, 9)) + +class B { b = "b"; } +>B : Symbol(B, Decl(sharedMemberLayoutGenericBase1.ts, 6, 18)) +>b : Symbol(B.b, Decl(sharedMemberLayoutGenericBase1.ts, 7, 9)) + +const DA = factory(A); +>DA : Symbol(DA, Decl(sharedMemberLayoutGenericBase1.ts, 9, 5)) +>factory : Symbol(factory, Decl(sharedMemberLayoutGenericBase1.ts, 0, 0)) +>A : Symbol(A, Decl(sharedMemberLayoutGenericBase1.ts, 4, 1)) + +const a = new DA(); +>a : Symbol(a, Decl(sharedMemberLayoutGenericBase1.ts, 10, 5)) +>DA : Symbol(DA, Decl(sharedMemberLayoutGenericBase1.ts, 9, 5)) + +const aValue: number = a.a; +>aValue : Symbol(aValue, Decl(sharedMemberLayoutGenericBase1.ts, 11, 5)) +>a.a : Symbol(A.a, Decl(sharedMemberLayoutGenericBase1.ts, 6, 9)) +>a : Symbol(a, Decl(sharedMemberLayoutGenericBase1.ts, 10, 5)) +>a : Symbol(A.a, Decl(sharedMemberLayoutGenericBase1.ts, 6, 9)) + +const aAll = { ...a }; +>aAll : Symbol(aAll, Decl(sharedMemberLayoutGenericBase1.ts, 12, 5)) +>a : Symbol(a, Decl(sharedMemberLayoutGenericBase1.ts, 10, 5)) + +const DB = factory(B); +>DB : Symbol(DB, Decl(sharedMemberLayoutGenericBase1.ts, 14, 5)) +>factory : Symbol(factory, Decl(sharedMemberLayoutGenericBase1.ts, 0, 0)) +>B : Symbol(B, Decl(sharedMemberLayoutGenericBase1.ts, 6, 18)) + +const b = new DB(); +>b : Symbol(b, Decl(sharedMemberLayoutGenericBase1.ts, 15, 5)) +>DB : Symbol(DB, Decl(sharedMemberLayoutGenericBase1.ts, 14, 5)) + +const bValue: string = b.b; +>bValue : Symbol(bValue, Decl(sharedMemberLayoutGenericBase1.ts, 16, 5)) +>b.b : Symbol(B.b, Decl(sharedMemberLayoutGenericBase1.ts, 7, 9)) +>b : Symbol(b, Decl(sharedMemberLayoutGenericBase1.ts, 15, 5)) +>b : Symbol(B.b, Decl(sharedMemberLayoutGenericBase1.ts, 7, 9)) + +const bAll = { ...b }; +>bAll : Symbol(bAll, Decl(sharedMemberLayoutGenericBase1.ts, 17, 5)) +>b : Symbol(b, Decl(sharedMemberLayoutGenericBase1.ts, 15, 5)) + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.types b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.types new file mode 100644 index 0000000000000..1c2e2434194ae --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase1.types @@ -0,0 +1,73 @@ +//// [tests/cases/compiler/sharedMemberLayoutGenericBase1.ts] //// + +=== sharedMemberLayoutGenericBase1.ts === +function factory(ctor: new () => T) { +>factory : (ctor: new () => T) => typeof Derived +>ctor : new () => T + + class Base extends ctor {} +>Base : Base +>ctor : T + + class Derived extends Base {} +>Derived : Derived +>Base : Base + + return Derived; +>Derived : typeof Derived +} + +class A { a = 1; } +>A : A +>a : number +>1 : 1 + +class B { b = "b"; } +>B : B +>b : string +>"b" : "b" + +const DA = factory(A); +>DA : typeof Derived +>factory(A) : typeof Derived +>factory : (ctor: new () => T) => typeof Derived +>A : typeof A + +const a = new DA(); +>a : factory.Derived +>new DA() : factory.Derived +>DA : typeof Derived + +const aValue: number = a.a; +>aValue : number +>a.a : number +>a : factory.Derived +>a : number + +const aAll = { ...a }; +>aAll : { a: number; } +>{ ...a } : { a: number; } +>a : factory.Derived + +const DB = factory(B); +>DB : typeof Derived +>factory(B) : typeof Derived +>factory : (ctor: new () => T) => typeof Derived +>B : typeof B + +const b = new DB(); +>b : factory.Derived +>new DB() : factory.Derived +>DB : typeof Derived + +const bValue: string = b.b; +>bValue : string +>b.b : string +>b : factory.Derived +>b : string + +const bAll = { ...b }; +>bAll : { b: string; } +>{ ...b } : { b: string; } +>b : factory.Derived + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.symbols b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.symbols new file mode 100644 index 0000000000000..83f58feb041c5 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.symbols @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/sharedMemberLayoutGenericBase2.ts] //// + +=== sharedMemberLayoutGenericBase2.ts === +declare function queryOptions(): Omit<{ +>queryOptions : Symbol(queryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 0, 0)) +>U : Symbol(U, Decl(sharedMemberLayoutGenericBase2.ts, 0, 30)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) + + queryKey: string; +>queryKey : Symbol(queryKey, Decl(sharedMemberLayoutGenericBase2.ts, 0, 42)) + + queryFn: () => { slug: string }; +>queryFn : Symbol(queryFn, Decl(sharedMemberLayoutGenericBase2.ts, 1, 21)) +>slug : Symbol(slug, Decl(sharedMemberLayoutGenericBase2.ts, 2, 20)) + +}, keyof U>; +>U : Symbol(U, Decl(sharedMemberLayoutGenericBase2.ts, 0, 30)) + +// Keep the call before the interface declarations. +const resume = ensureQueryData(queryOptions()); +>resume : Symbol(resume, Decl(sharedMemberLayoutGenericBase2.ts, 6, 5)) +>ensureQueryData : Symbol(ensureQueryData, Decl(sharedMemberLayoutGenericBase2.ts, 19, 38)) +>queryOptions : Symbol(queryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 0, 0)) + +resume.slug; +>resume.slug : Symbol(slug, Decl(sharedMemberLayoutGenericBase2.ts, 2, 20)) +>resume : Symbol(resume, Decl(sharedMemberLayoutGenericBase2.ts, 6, 5)) +>slug : Symbol(slug, Decl(sharedMemberLayoutGenericBase2.ts, 2, 20)) + +interface QueryOptions { +>QueryOptions : Symbol(QueryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 7, 12)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 9, 23)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 9, 25)) + + queryKey?: K; +>queryKey : Symbol(QueryOptions.queryKey, Decl(sharedMemberLayoutGenericBase2.ts, 9, 30)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 9, 25)) + + queryFn?: () => T; +>queryFn : Symbol(QueryOptions.queryFn, Decl(sharedMemberLayoutGenericBase2.ts, 10, 17)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 9, 23)) +} +type WithRequired = T & { queryKey: {} }; +>WithRequired : Symbol(WithRequired, Decl(sharedMemberLayoutGenericBase2.ts, 12, 1)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 13, 18)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 13, 18)) +>queryKey : Symbol(queryKey, Decl(sharedMemberLayoutGenericBase2.ts, 13, 28)) + +interface FetchQueryOptions +>FetchQueryOptions : Symbol(FetchQueryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 13, 44)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 14, 28)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 14, 30)) + + extends WithRequired> { +>WithRequired : Symbol(WithRequired, Decl(sharedMemberLayoutGenericBase2.ts, 12, 1)) +>QueryOptions : Symbol(QueryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 7, 12)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 14, 28)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 14, 30)) + + initialPageParam?: never; +>initialPageParam : Symbol(FetchQueryOptions.initialPageParam, Decl(sharedMemberLayoutGenericBase2.ts, 15, 46)) +} +interface EnsureQueryDataOptions +>EnsureQueryDataOptions : Symbol(EnsureQueryDataOptions, Decl(sharedMemberLayoutGenericBase2.ts, 17, 1)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 18, 33)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 18, 35)) + + extends FetchQueryOptions {} +>FetchQueryOptions : Symbol(FetchQueryOptions, Decl(sharedMemberLayoutGenericBase2.ts, 13, 44)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 18, 33)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 18, 35)) + +declare function ensureQueryData( +>ensureQueryData : Symbol(ensureQueryData, Decl(sharedMemberLayoutGenericBase2.ts, 19, 38)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 21, 33)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 21, 35)) + + options: EnsureQueryDataOptions +>options : Symbol(options, Decl(sharedMemberLayoutGenericBase2.ts, 21, 39)) +>EnsureQueryDataOptions : Symbol(EnsureQueryDataOptions, Decl(sharedMemberLayoutGenericBase2.ts, 17, 1)) +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 21, 33)) +>K : Symbol(K, Decl(sharedMemberLayoutGenericBase2.ts, 21, 35)) + +): T; +>T : Symbol(T, Decl(sharedMemberLayoutGenericBase2.ts, 21, 33)) + +export {}; + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.types b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.types new file mode 100644 index 0000000000000..a24804871dac8 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutGenericBase2.types @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/sharedMemberLayoutGenericBase2.ts] //// + +=== sharedMemberLayoutGenericBase2.ts === +declare function queryOptions(): Omit<{ +>queryOptions : () => Omit<{ queryKey: string; queryFn: () => { slug: string; }; }, keyof U> + + queryKey: string; +>queryKey : string + + queryFn: () => { slug: string }; +>queryFn : () => { slug: string; } +>slug : string + +}, keyof U>; + +// Keep the call before the interface declarations. +const resume = ensureQueryData(queryOptions()); +>resume : { slug: string; } +>ensureQueryData(queryOptions()) : { slug: string; } +>ensureQueryData : (options: EnsureQueryDataOptions) => T +>queryOptions() : Omit<{ queryKey: string; queryFn: () => { slug: string; }; }, never> +>queryOptions : () => Omit<{ queryKey: string; queryFn: () => { slug: string; }; }, keyof U> + +resume.slug; +>resume.slug : string +>resume : { slug: string; } +>slug : string + +interface QueryOptions { + queryKey?: K; +>queryKey : K | undefined + + queryFn?: () => T; +>queryFn : (() => T) | undefined +} +type WithRequired = T & { queryKey: {} }; +>WithRequired : WithRequired +>queryKey : {} + +interface FetchQueryOptions + extends WithRequired> { + initialPageParam?: never; +>initialPageParam : undefined +} +interface EnsureQueryDataOptions + extends FetchQueryOptions {} + +declare function ensureQueryData( +>ensureQueryData : (options: EnsureQueryDataOptions) => T + + options: EnsureQueryDataOptions +>options : EnsureQueryDataOptions + +): T; + +export {}; + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.errors.txt b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.errors.txt new file mode 100644 index 0000000000000..38ea8e221e2e3 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.errors.txt @@ -0,0 +1,36 @@ +sharedMemberLayoutThisIntersectionBase.ts(5,11): error TS2589: Type instantiation is excessively deep and possibly infinite. +sharedMemberLayoutThisIntersectionBase.ts(7,1): error TS2589: Type instantiation is excessively deep and possibly infinite. +sharedMemberLayoutThisIntersectionBase.ts(7,3): error TS2339: Property 'm' does not exist on type 'D<"b">'. +sharedMemberLayoutThisIntersectionBase.ts(10,7): error TS2589: Type instantiation is excessively deep and possibly infinite. +sharedMemberLayoutThisIntersectionBase.ts(12,1): error TS2589: Type instantiation is excessively deep and possibly infinite. +sharedMemberLayoutThisIntersectionBase.ts(12,3): error TS2339: Property 'm' does not exist on type 'C<"b">'. + + +==== sharedMemberLayoutThisIntersectionBase.ts (6 errors) ==== + interface A { kind: string; m: this["kind"] } + interface B { m: "a" } + type AB = A & B; + + interface D extends AB { kind: T } + ~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + declare let d: D<"b">; + d.m; + ~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + ~ +!!! error TS2339: Property 'm' does not exist on type 'D<"b">'. + + declare const ABCtor: new () => AB; + class C extends ABCtor { declare kind: T } + ~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + declare let c: C<"b">; + c.m; + ~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + ~ +!!! error TS2339: Property 'm' does not exist on type 'C<"b">'. + + export {}; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.symbols b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.symbols new file mode 100644 index 0000000000000..793b38f82728b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/sharedMemberLayoutThisIntersectionBase.ts] //// + +=== sharedMemberLayoutThisIntersectionBase.ts === +interface A { kind: string; m: this["kind"] } +>A : Symbol(A, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 0)) +>kind : Symbol(A.kind, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 13)) +>m : Symbol(A.m, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 27)) + +interface B { m: "a" } +>B : Symbol(B, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 45)) +>m : Symbol(B.m, Decl(sharedMemberLayoutThisIntersectionBase.ts, 1, 13)) + +type AB = A & B; +>AB : Symbol(AB, Decl(sharedMemberLayoutThisIntersectionBase.ts, 1, 22)) +>A : Symbol(A, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 0)) +>B : Symbol(B, Decl(sharedMemberLayoutThisIntersectionBase.ts, 0, 45)) + +interface D extends AB { kind: T } +>D : Symbol(D, Decl(sharedMemberLayoutThisIntersectionBase.ts, 2, 16)) +>T : Symbol(T, Decl(sharedMemberLayoutThisIntersectionBase.ts, 4, 12)) +>AB : Symbol(AB, Decl(sharedMemberLayoutThisIntersectionBase.ts, 1, 22)) +>kind : Symbol(D.kind, Decl(sharedMemberLayoutThisIntersectionBase.ts, 4, 42)) +>T : Symbol(T, Decl(sharedMemberLayoutThisIntersectionBase.ts, 4, 12)) + +declare let d: D<"b">; +>d : Symbol(d, Decl(sharedMemberLayoutThisIntersectionBase.ts, 5, 11)) +>D : Symbol(D, Decl(sharedMemberLayoutThisIntersectionBase.ts, 2, 16)) + +d.m; +>d : Symbol(d, Decl(sharedMemberLayoutThisIntersectionBase.ts, 5, 11)) + +declare const ABCtor: new () => AB; +>ABCtor : Symbol(ABCtor, Decl(sharedMemberLayoutThisIntersectionBase.ts, 8, 13)) +>AB : Symbol(AB, Decl(sharedMemberLayoutThisIntersectionBase.ts, 1, 22)) + +class C extends ABCtor { declare kind: T } +>C : Symbol(C, Decl(sharedMemberLayoutThisIntersectionBase.ts, 8, 35)) +>T : Symbol(T, Decl(sharedMemberLayoutThisIntersectionBase.ts, 9, 8)) +>ABCtor : Symbol(ABCtor, Decl(sharedMemberLayoutThisIntersectionBase.ts, 8, 13)) +>kind : Symbol(C.kind, Decl(sharedMemberLayoutThisIntersectionBase.ts, 9, 42)) +>T : Symbol(T, Decl(sharedMemberLayoutThisIntersectionBase.ts, 9, 8)) + +declare let c: C<"b">; +>c : Symbol(c, Decl(sharedMemberLayoutThisIntersectionBase.ts, 10, 11)) +>C : Symbol(C, Decl(sharedMemberLayoutThisIntersectionBase.ts, 8, 35)) + +c.m; +>c : Symbol(c, Decl(sharedMemberLayoutThisIntersectionBase.ts, 10, 11)) + +export {}; + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.types b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.types new file mode 100644 index 0000000000000..41de65a71ea2f --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutThisIntersectionBase.types @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/sharedMemberLayoutThisIntersectionBase.ts] //// + +=== sharedMemberLayoutThisIntersectionBase.ts === +interface A { kind: string; m: this["kind"] } +>kind : string +>m : this["kind"] + +interface B { m: "a" } +>m : "a" + +type AB = A & B; +>AB : AB + +interface D extends AB { kind: T } +>kind : T + +declare let d: D<"b">; +>d : D<"b"> + +d.m; +>d.m : any +>d : D<"b"> +>m : any + +declare const ABCtor: new () => AB; +>ABCtor : new () => AB + +class C extends ABCtor { declare kind: T } +>C : C +>ABCtor : A & B +>kind : T + +declare let c: C<"b">; +>c : C<"b"> + +c.m; +>c.m : any +>c : C<"b"> +>m : any + +export {}; + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.errors.txt b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.errors.txt new file mode 100644 index 0000000000000..a75a8eb9fe3b8 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.errors.txt @@ -0,0 +1,18 @@ +sharedMemberLayoutTupleBases.ts(4,11): error TS2430: Interface 'FromTuple' incorrectly extends interface '[number, ...T]'. + + +==== sharedMemberLayoutTupleBases.ts (1 errors) ==== + // Each tuple base can have a different target, and so a different member layout. + + type Prefixed = [number, ...T]; + interface FromTuple extends Prefixed {} + ~~~~~~~~~ +!!! error TS2430: Interface 'FromTuple' incorrectly extends interface '[number, ...T]'. + declare const generic: FromTuple; + const genericFirst = generic[0]; + const genericAll = { ...generic }; + declare const fixed: FromTuple<[string]>; + const fixedSecond = fixed[1]; + const fixedAll = { ...fixed }; + + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.symbols b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.symbols new file mode 100644 index 0000000000000..663335099427d --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.symbols @@ -0,0 +1,43 @@ +//// [tests/cases/compiler/sharedMemberLayoutTupleBases.ts] //// + +=== sharedMemberLayoutTupleBases.ts === +// Each tuple base can have a different target, and so a different member layout. + +type Prefixed = [number, ...T]; +>Prefixed : Symbol(Prefixed, Decl(sharedMemberLayoutTupleBases.ts, 0, 0)) +>T : Symbol(T, Decl(sharedMemberLayoutTupleBases.ts, 2, 14)) +>T : Symbol(T, Decl(sharedMemberLayoutTupleBases.ts, 2, 14)) + +interface FromTuple extends Prefixed {} +>FromTuple : Symbol(FromTuple, Decl(sharedMemberLayoutTupleBases.ts, 2, 52)) +>T : Symbol(T, Decl(sharedMemberLayoutTupleBases.ts, 3, 20)) +>Prefixed : Symbol(Prefixed, Decl(sharedMemberLayoutTupleBases.ts, 0, 0)) +>T : Symbol(T, Decl(sharedMemberLayoutTupleBases.ts, 3, 20)) + +declare const generic: FromTuple; +>generic : Symbol(generic, Decl(sharedMemberLayoutTupleBases.ts, 4, 13)) +>FromTuple : Symbol(FromTuple, Decl(sharedMemberLayoutTupleBases.ts, 2, 52)) + +const genericFirst = generic[0]; +>genericFirst : Symbol(genericFirst, Decl(sharedMemberLayoutTupleBases.ts, 5, 5)) +>generic : Symbol(generic, Decl(sharedMemberLayoutTupleBases.ts, 4, 13)) +>0 : Symbol(0) + +const genericAll = { ...generic }; +>genericAll : Symbol(genericAll, Decl(sharedMemberLayoutTupleBases.ts, 6, 5)) +>generic : Symbol(generic, Decl(sharedMemberLayoutTupleBases.ts, 4, 13)) + +declare const fixed: FromTuple<[string]>; +>fixed : Symbol(fixed, Decl(sharedMemberLayoutTupleBases.ts, 7, 13)) +>FromTuple : Symbol(FromTuple, Decl(sharedMemberLayoutTupleBases.ts, 2, 52)) + +const fixedSecond = fixed[1]; +>fixedSecond : Symbol(fixedSecond, Decl(sharedMemberLayoutTupleBases.ts, 8, 5)) +>fixed : Symbol(fixed, Decl(sharedMemberLayoutTupleBases.ts, 7, 13)) +>1 : Symbol(1) + +const fixedAll = { ...fixed }; +>fixedAll : Symbol(fixedAll, Decl(sharedMemberLayoutTupleBases.ts, 9, 5)) +>fixed : Symbol(fixed, Decl(sharedMemberLayoutTupleBases.ts, 7, 13)) + + diff --git a/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.types b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.types new file mode 100644 index 0000000000000..3e170e1ab7d6e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/sharedMemberLayoutTupleBases.types @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/sharedMemberLayoutTupleBases.ts] //// + +=== sharedMemberLayoutTupleBases.ts === +// Each tuple base can have a different target, and so a different member layout. + +type Prefixed = [number, ...T]; +>Prefixed : [number, ...T] + +interface FromTuple extends Prefixed {} +declare const generic: FromTuple; +>generic : FromTuple + +const genericFirst = generic[0]; +>genericFirst : number +>generic[0] : number +>generic : FromTuple +>0 : 0 + +const genericAll = { ...generic }; +>genericAll : { [n: number]: unknown; toString(): string; toLocaleString(): string; toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; pop(): unknown; push(...items: unknown[]): number; concat(...items: ConcatArray[]): unknown[]; concat(...items: unknown[]): unknown[]; join(separator?: string): string; reverse(): unknown[]; shift(): unknown; slice(start?: number, end?: number): unknown[]; sort(compareFn?: ((a: unknown, b: unknown) => number) | undefined): FromTuple; splice(start: number, deleteCount?: number): unknown[]; splice(start: number, deleteCount: number, ...items: unknown[]): unknown[]; unshift(...items: unknown[]): number; indexOf(searchElement: unknown, fromIndex?: number): number; lastIndexOf(searchElement: unknown, fromIndex?: number): number; every(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): boolean; some(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: unknown, index: number, array: unknown[]) => void, thisArg?: any): void; map(callbackfn: (value: unknown, index: number, array: unknown[]) => U, thisArg?: any): U[]; filter(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): unknown[]; reduce(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown): unknown; reduce(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown, initialValue: unknown): unknown; reduce(callbackfn: (previousValue: U, currentValue: unknown, currentIndex: number, array: unknown[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown): unknown; reduceRight(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown, initialValue: unknown): unknown; reduceRight(callbackfn: (previousValue: U, currentValue: unknown, currentIndex: number, array: unknown[]) => U, initialValue: U): U; find(predicate: (value: unknown, index: number, obj: unknown[]) => value is S, thisArg?: any): S | undefined; find(predicate: (value: unknown, index: number, obj: unknown[]) => unknown, thisArg?: any): unknown; findIndex(predicate: (value: unknown, index: number, obj: unknown[]) => unknown, thisArg?: any): number; fill(value: unknown, start?: number, end?: number): FromTuple; copyWithin(target: number, start: number, end?: number): FromTuple; [Symbol.iterator](): ArrayIterator; entries(): ArrayIterator<[number, unknown]>; keys(): ArrayIterator; values(): ArrayIterator; [Symbol.unscopables]: { [x: number]: boolean | undefined; length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; pop?: boolean | undefined; push?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; reverse?: boolean | undefined; shift?: boolean | undefined; slice?: boolean | undefined; sort?: boolean | undefined; splice?: boolean | undefined; unshift?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; fill?: boolean | undefined; copyWithin?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; findLast?: boolean | undefined; findLastIndex?: boolean | undefined; toReversed?: boolean | undefined; toSorted?: boolean | undefined; toSpliced?: boolean | undefined; with?: boolean | undefined; }; includes(searchElement: unknown, fromIndex?: number): boolean; flatMap(callback: (this: This, value: unknown, index: number, array: unknown[]) => U | readonly U[], thisArg?: This | undefined): U[]; flat(this: A, depth?: D | undefined): FlatArray[]; at(index: number): unknown; findLast(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): S | undefined; findLast(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): unknown; findLastIndex(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): number; toReversed(): unknown[]; toSorted(compareFn?: ((a: unknown, b: unknown) => number) | undefined): unknown[]; toSpliced(start: number, deleteCount: number, ...items: unknown[]): unknown[]; toSpliced(start: number, deleteCount?: number): unknown[]; with(index: number, value: unknown): unknown[]; 0: number; length: number; } +>{ ...generic } : { [n: number]: unknown; toString(): string; toLocaleString(): string; toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; pop(): unknown; push(...items: unknown[]): number; concat(...items: ConcatArray[]): unknown[]; concat(...items: unknown[]): unknown[]; join(separator?: string): string; reverse(): unknown[]; shift(): unknown; slice(start?: number, end?: number): unknown[]; sort(compareFn?: ((a: unknown, b: unknown) => number) | undefined): FromTuple; splice(start: number, deleteCount?: number): unknown[]; splice(start: number, deleteCount: number, ...items: unknown[]): unknown[]; unshift(...items: unknown[]): number; indexOf(searchElement: unknown, fromIndex?: number): number; lastIndexOf(searchElement: unknown, fromIndex?: number): number; every(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): boolean; some(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: unknown, index: number, array: unknown[]) => void, thisArg?: any): void; map(callbackfn: (value: unknown, index: number, array: unknown[]) => U, thisArg?: any): U[]; filter(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): unknown[]; reduce(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown): unknown; reduce(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown, initialValue: unknown): unknown; reduce(callbackfn: (previousValue: U, currentValue: unknown, currentIndex: number, array: unknown[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown): unknown; reduceRight(callbackfn: (previousValue: unknown, currentValue: unknown, currentIndex: number, array: unknown[]) => unknown, initialValue: unknown): unknown; reduceRight(callbackfn: (previousValue: U, currentValue: unknown, currentIndex: number, array: unknown[]) => U, initialValue: U): U; find(predicate: (value: unknown, index: number, obj: unknown[]) => value is S, thisArg?: any): S | undefined; find(predicate: (value: unknown, index: number, obj: unknown[]) => unknown, thisArg?: any): unknown; findIndex(predicate: (value: unknown, index: number, obj: unknown[]) => unknown, thisArg?: any): number; fill(value: unknown, start?: number, end?: number): FromTuple; copyWithin(target: number, start: number, end?: number): FromTuple; [Symbol.iterator](): ArrayIterator; entries(): ArrayIterator<[number, unknown]>; keys(): ArrayIterator; values(): ArrayIterator; [Symbol.unscopables]: { [x: number]: boolean | undefined; length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; pop?: boolean | undefined; push?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; reverse?: boolean | undefined; shift?: boolean | undefined; slice?: boolean | undefined; sort?: boolean | undefined; splice?: boolean | undefined; unshift?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; fill?: boolean | undefined; copyWithin?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; findLast?: boolean | undefined; findLastIndex?: boolean | undefined; toReversed?: boolean | undefined; toSorted?: boolean | undefined; toSpliced?: boolean | undefined; with?: boolean | undefined; }; includes(searchElement: unknown, fromIndex?: number): boolean; flatMap(callback: (this: This, value: unknown, index: number, array: unknown[]) => U | readonly U[], thisArg?: This | undefined): U[]; flat(this: A, depth?: D | undefined): FlatArray[]; at(index: number): unknown; findLast(predicate: (value: unknown, index: number, array: unknown[]) => value is S, thisArg?: any): S | undefined; findLast(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): unknown; findLastIndex(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): number; toReversed(): unknown[]; toSorted(compareFn?: ((a: unknown, b: unknown) => number) | undefined): unknown[]; toSpliced(start: number, deleteCount: number, ...items: unknown[]): unknown[]; toSpliced(start: number, deleteCount?: number): unknown[]; with(index: number, value: unknown): unknown[]; 0: number; length: number; } +>generic : FromTuple + +declare const fixed: FromTuple<[string]>; +>fixed : FromTuple<[string]> + +const fixedSecond = fixed[1]; +>fixedSecond : string +>fixed[1] : string +>fixed : FromTuple<[string]> +>1 : 1 + +const fixedAll = { ...fixed }; +>fixedAll : { [n: number]: string | number; toString(): string; toLocaleString(): string; toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; pop(): string | number | undefined; push(...items: (string | number)[]): number; concat(...items: ConcatArray[]): (string | number)[]; concat(...items: (string | number | ConcatArray)[]): (string | number)[]; join(separator?: string): string; reverse(): (string | number)[]; shift(): string | number | undefined; slice(start?: number, end?: number): (string | number)[]; sort(compareFn?: ((a: string | number, b: string | number) => number) | undefined): FromTuple<[string]>; splice(start: number, deleteCount?: number): (string | number)[]; splice(start: number, deleteCount: number, ...items: (string | number)[]): (string | number)[]; unshift(...items: (string | number)[]): number; indexOf(searchElement: string | number, fromIndex?: number): number; lastIndexOf(searchElement: string | number, fromIndex?: number): number; every(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; some(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: string | number, index: number, array: (string | number)[]) => void, thisArg?: any): void; map(callbackfn: (value: string | number, index: number, array: (string | number)[]) => U, thisArg?: any): U[]; filter(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): (string | number)[]; reduce(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number): string | number; reduce(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number, initialValue: string | number): string | number; reduce(callbackfn: (previousValue: U, currentValue: string | number, currentIndex: number, array: (string | number)[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number): string | number; reduceRight(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number, initialValue: string | number): string | number; reduceRight(callbackfn: (previousValue: U, currentValue: string | number, currentIndex: number, array: (string | number)[]) => U, initialValue: U): U; find(predicate: (value: string | number, index: number, obj: (string | number)[]) => value is S, thisArg?: any): S | undefined; find(predicate: (value: string | number, index: number, obj: (string | number)[]) => unknown, thisArg?: any): string | number | undefined; findIndex(predicate: (value: string | number, index: number, obj: (string | number)[]) => unknown, thisArg?: any): number; fill(value: string | number, start?: number, end?: number): FromTuple<[string]>; copyWithin(target: number, start: number, end?: number): FromTuple<[string]>; [Symbol.iterator](): ArrayIterator; entries(): ArrayIterator<[number, string | number]>; keys(): ArrayIterator; values(): ArrayIterator; [Symbol.unscopables]: { [x: number]: boolean | undefined; length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; pop?: boolean | undefined; push?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; reverse?: boolean | undefined; shift?: boolean | undefined; slice?: boolean | undefined; sort?: boolean | undefined; splice?: boolean | undefined; unshift?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; fill?: boolean | undefined; copyWithin?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; findLast?: boolean | undefined; findLastIndex?: boolean | undefined; toReversed?: boolean | undefined; toSorted?: boolean | undefined; toSpliced?: boolean | undefined; with?: boolean | undefined; }; includes(searchElement: string | number, fromIndex?: number): boolean; flatMap(callback: (this: This, value: string | number, index: number, array: (string | number)[]) => U | readonly U[], thisArg?: This | undefined): U[]; flat(this: A, depth?: D | undefined): FlatArray[]; at(index: number): string | number | undefined; findLast(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): S | undefined; findLast(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): string | number | undefined; findLastIndex(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): number; toReversed(): (string | number)[]; toSorted(compareFn?: ((a: string | number, b: string | number) => number) | undefined): (string | number)[]; toSpliced(start: number, deleteCount: number, ...items: (string | number)[]): (string | number)[]; toSpliced(start: number, deleteCount?: number): (string | number)[]; with(index: number, value: string | number): (string | number)[]; 0: number; 1: string; length: 2; } +>{ ...fixed } : { [n: number]: string | number; toString(): string; toLocaleString(): string; toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string; pop(): string | number | undefined; push(...items: (string | number)[]): number; concat(...items: ConcatArray[]): (string | number)[]; concat(...items: (string | number | ConcatArray)[]): (string | number)[]; join(separator?: string): string; reverse(): (string | number)[]; shift(): string | number | undefined; slice(start?: number, end?: number): (string | number)[]; sort(compareFn?: ((a: string | number, b: string | number) => number) | undefined): FromTuple<[string]>; splice(start: number, deleteCount?: number): (string | number)[]; splice(start: number, deleteCount: number, ...items: (string | number)[]): (string | number)[]; unshift(...items: (string | number)[]): number; indexOf(searchElement: string | number, fromIndex?: number): number; lastIndexOf(searchElement: string | number, fromIndex?: number): number; every(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; some(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: string | number, index: number, array: (string | number)[]) => void, thisArg?: any): void; map(callbackfn: (value: string | number, index: number, array: (string | number)[]) => U, thisArg?: any): U[]; filter(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): (string | number)[]; reduce(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number): string | number; reduce(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number, initialValue: string | number): string | number; reduce(callbackfn: (previousValue: U, currentValue: string | number, currentIndex: number, array: (string | number)[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number): string | number; reduceRight(callbackfn: (previousValue: string | number, currentValue: string | number, currentIndex: number, array: (string | number)[]) => string | number, initialValue: string | number): string | number; reduceRight(callbackfn: (previousValue: U, currentValue: string | number, currentIndex: number, array: (string | number)[]) => U, initialValue: U): U; find(predicate: (value: string | number, index: number, obj: (string | number)[]) => value is S, thisArg?: any): S | undefined; find(predicate: (value: string | number, index: number, obj: (string | number)[]) => unknown, thisArg?: any): string | number | undefined; findIndex(predicate: (value: string | number, index: number, obj: (string | number)[]) => unknown, thisArg?: any): number; fill(value: string | number, start?: number, end?: number): FromTuple<[string]>; copyWithin(target: number, start: number, end?: number): FromTuple<[string]>; [Symbol.iterator](): ArrayIterator; entries(): ArrayIterator<[number, string | number]>; keys(): ArrayIterator; values(): ArrayIterator; [Symbol.unscopables]: { [x: number]: boolean | undefined; length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; pop?: boolean | undefined; push?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; reverse?: boolean | undefined; shift?: boolean | undefined; slice?: boolean | undefined; sort?: boolean | undefined; splice?: boolean | undefined; unshift?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; fill?: boolean | undefined; copyWithin?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; findLast?: boolean | undefined; findLastIndex?: boolean | undefined; toReversed?: boolean | undefined; toSorted?: boolean | undefined; toSpliced?: boolean | undefined; with?: boolean | undefined; }; includes(searchElement: string | number, fromIndex?: number): boolean; flatMap(callback: (this: This, value: string | number, index: number, array: (string | number)[]) => U | readonly U[], thisArg?: This | undefined): U[]; flat(this: A, depth?: D | undefined): FlatArray[]; at(index: number): string | number | undefined; findLast(predicate: (value: string | number, index: number, array: (string | number)[]) => value is S, thisArg?: any): S | undefined; findLast(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): string | number | undefined; findLastIndex(predicate: (value: string | number, index: number, array: (string | number)[]) => unknown, thisArg?: any): number; toReversed(): (string | number)[]; toSorted(compareFn?: ((a: string | number, b: string | number) => number) | undefined): (string | number)[]; toSpliced(start: number, deleteCount: number, ...items: (string | number)[]): (string | number)[]; toSpliced(start: number, deleteCount?: number): (string | number)[]; with(index: number, value: string | number): (string | number)[]; 0: number; 1: string; length: 2; } +>fixed : FromTuple<[string]> + + diff --git a/tsc/testdata/baselines/reference/conformance/arityAndOrderCompatibility01.errors.txt b/tsc/testdata/baselines/reference/conformance/arityAndOrderCompatibility01.errors.txt index 4ffe9f08b720d..5e19ee4881f40 100644 --- a/tsc/testdata/baselines/reference/conformance/arityAndOrderCompatibility01.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/arityAndOrderCompatibility01.errors.txt @@ -11,16 +11,14 @@ arityAndOrderCompatibility01.ts(23,5): error TS2322: Type '{ 0: string; 1: numbe arityAndOrderCompatibility01.ts(24,5): error TS2322: Type '[string, number]' is not assignable to type '[number]'. Source has 2 element(s) but target allows only 1. arityAndOrderCompatibility01.ts(25,5): error TS2322: Type 'StrNum' is not assignable to type '[number]'. - The types returned by 'pop()' are incompatible between these types. - Type 'string | number | undefined' is not assignable to type 'number | undefined'. - Type 'string' is not assignable to type 'number'. + Types of property '0' are incompatible. + Type 'string' is not assignable to type 'number'. arityAndOrderCompatibility01.ts(26,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number]'. arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '[string, number]' is not assignable to type '[string]'. Source has 2 element(s) but target allows only 1. arityAndOrderCompatibility01.ts(28,5): error TS2322: Type 'StrNum' is not assignable to type '[string]'. - The types returned by 'pop()' are incompatible between these types. - Type 'string | number | undefined' is not assignable to type 'string | undefined'. - Type 'number' is not assignable to type 'string'. + Types of property 'length' are incompatible. + Type '2' is not assignable to type '1'. arityAndOrderCompatibility01.ts(29,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string]'. arityAndOrderCompatibility01.ts(30,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. Type at position 0 in source is not compatible with type at position 0 in target. @@ -80,9 +78,8 @@ arityAndOrderCompatibility01.ts(32,5): error TS2322: Type '{ 0: string; 1: numbe var l2: [number] = y; ~~ !!! error TS2322: Type 'StrNum' is not assignable to type '[number]'. -!!! error TS2322: The types returned by 'pop()' are incompatible between these types. -!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'number | undefined'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property '0' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'number'. var l3: [number] = z; ~~ !!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number]'. @@ -93,9 +90,8 @@ arityAndOrderCompatibility01.ts(32,5): error TS2322: Type '{ 0: string; 1: numbe var m2: [string] = y; ~~ !!! error TS2322: Type 'StrNum' is not assignable to type '[string]'. -!!! error TS2322: The types returned by 'pop()' are incompatible between these types. -!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'string | undefined'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '2' is not assignable to type '1'. var m3: [string] = z; ~~ !!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string]'. diff --git a/tsc/testdata/tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts b/tsc/testdata/tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts new file mode 100644 index 0000000000000..e998bc6d2c356 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts @@ -0,0 +1,26 @@ +// @target: esnext +// @strict: true +// @declaration: true + +declare const rI: RI<"a">; +rI.x +interface RI { + x: T; + [rI.x]: "b"; +} +declare const rI2: RI<"b">; +export const v1 = rI2.a; +export const v2 = rI.a; +export type K2 = keyof RI<"b">; +export const k: K2 = "a"; +export const o: RI<"b"> = { x: "b", a: "b" }; + +declare const rC: RC<"a">; +rC.x +declare class RC { + x: T; + [rC.x]: "b"; +} +declare const rC2: RC<"b">; +export const w1 = rC2.a; +export const w2 = rC.a; diff --git a/tsc/testdata/tests/cases/compiler/lazyInheritedMemberLookup.ts b/tsc/testdata/tests/cases/compiler/lazyInheritedMemberLookup.ts new file mode 100644 index 0000000000000..87beb549f9766 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/lazyInheritedMemberLookup.ts @@ -0,0 +1,41 @@ +// @strict: true +// @noEmit: true + +// Inherited members are looked up individually before the members of each type are enumerated. + +interface Grand { + grand: T; + shared: T; +} +type Mixin = { mixin: T }; +type Fixed = { fixed: string }; +interface Base extends Grand { + base: T; +} +interface Derived extends Base, Mixin, Fixed { + shared: T[]; + derived: T; +} +class C { + declared!: T; +} +class D extends C implements Derived { + grand!: T[]; + shared!: T[]; + mixin!: T; + fixed!: string; + base!: T; + derived!: T; +} + +declare const d: Derived; +const grand = d.grand; +const mixin = d.mixin; +const fixed = d.fixed; +const shared = d.shared; +const all = { ...d }; +declare const keys: { [K in keyof Derived]: K }; + +declare const e: D; +const declared = e.declared; +const allE = { ...e }; diff --git a/tsc/testdata/tests/cases/compiler/namespaceImportOfCallableInterfaceExport.ts b/tsc/testdata/tests/cases/compiler/namespaceImportOfCallableInterfaceExport.ts new file mode 100644 index 0000000000000..2b587f0660178 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/namespaceImportOfCallableInterfaceExport.ts @@ -0,0 +1,20 @@ +// @module: commonjs +// @esModuleInterop: true,false +// @noEmit: true + +// @filename: mod.d.ts +interface Base { + value: T; +} +interface Callable extends Base { + (): void; + __esModule: true; + other: number; +} +declare const callable: Callable; +export = callable; + +// @filename: main.ts +import * as ns from "./mod"; +const value: string = ns.value; +const other: number = ns.other; diff --git a/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase1.ts b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase1.ts new file mode 100644 index 0000000000000..4b9c322b7539b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase1.ts @@ -0,0 +1,21 @@ +// @strict: true +// @noEmit: true + +function factory(ctor: new () => T) { + class Base extends ctor {} + class Derived extends Base {} + return Derived; +} + +class A { a = 1; } +class B { b = "b"; } + +const DA = factory(A); +const a = new DA(); +const aValue: number = a.a; +const aAll = { ...a }; + +const DB = factory(B); +const b = new DB(); +const bValue: string = b.b; +const bAll = { ...b }; diff --git a/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase2.ts b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase2.ts new file mode 100644 index 0000000000000..d7d77a98d155d --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutGenericBase2.ts @@ -0,0 +1,30 @@ +// @strict: true +// @target: esnext +// @noEmit: true + +declare function queryOptions(): Omit<{ + queryKey: string; + queryFn: () => { slug: string }; +}, keyof U>; + +// Keep the call before the interface declarations. +const resume = ensureQueryData(queryOptions()); +resume.slug; + +interface QueryOptions { + queryKey?: K; + queryFn?: () => T; +} +type WithRequired = T & { queryKey: {} }; +interface FetchQueryOptions + extends WithRequired> { + initialPageParam?: never; +} +interface EnsureQueryDataOptions + extends FetchQueryOptions {} + +declare function ensureQueryData( + options: EnsureQueryDataOptions +): T; + +export {}; diff --git a/tsc/testdata/tests/cases/compiler/sharedMemberLayoutThisIntersectionBase.ts b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutThisIntersectionBase.ts new file mode 100644 index 0000000000000..71209527ff35b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutThisIntersectionBase.ts @@ -0,0 +1,17 @@ +// @strict: true +// @noEmit: true + +interface A { kind: string; m: this["kind"] } +interface B { m: "a" } +type AB = A & B; + +interface D extends AB { kind: T } +declare let d: D<"b">; +d.m; + +declare const ABCtor: new () => AB; +class C extends ABCtor { declare kind: T } +declare let c: C<"b">; +c.m; + +export {}; diff --git a/tsc/testdata/tests/cases/compiler/sharedMemberLayoutTupleBases.ts b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutTupleBases.ts new file mode 100644 index 0000000000000..6bfee2e00f1c4 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/sharedMemberLayoutTupleBases.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +// Each tuple base can have a different target, and so a different member layout. + +type Prefixed = [number, ...T]; +interface FromTuple extends Prefixed {} +declare const generic: FromTuple; +const genericFirst = generic[0]; +const genericAll = { ...generic }; +declare const fixed: FromTuple<[string]>; +const fixedSecond = fixed[1]; +const fixedAll = { ...fixed }; +