@@ -23,6 +23,23 @@ func (b *nodeBuilderImpl) psuedoTypeToNode(t *psuedochecker.PsuedoType) *ast.Nod
2323 node := t .Data .(* psuedochecker.PsuedoTypeNoResult ).Declaration
2424 b .ctx .tracker .ReportInferenceFallback (node )
2525 return b .serializeTypeForDeclaration (node , nil , nil , false )
26+ case psuedochecker .PsuedoTypeKindMaybeConstLocation :
27+ d := t .Data .(* psuedochecker.PsuedoTypeMaybeConstLocation )
28+ // see checkExpressionWithContextualType for general literal widening rules which need to be emulated here, plus
29+ // checkTemplateLiteralExpression for template literal widening rules if the psuedochecker ever supports literalized templates
30+ isInConstContext := b .ch .isConstContext (d .Node )
31+ if ! isInConstContext {
32+ contextualType := b .ch .getContextualType (d .Node , ContextFlagsNone )
33+ t := b .psuedoTypeToType (d .ConstType )
34+ if t != nil && b .ch .isLiteralOfContextualType (t , b .ch .instantiateContextualType (contextualType , d .Node , ContextFlagsNone )) {
35+ isInConstContext = true
36+ }
37+ }
38+ if isInConstContext {
39+ return b .psuedoTypeToNode (d .ConstType )
40+ } else {
41+ return b .psuedoTypeToNode (d .RegularType )
42+ }
2643 case psuedochecker .PsuedoTypeKindUnion :
2744 var res []* ast.Node
2845 var hasElidedType bool
@@ -206,3 +223,72 @@ func (b *nodeBuilderImpl) psuedoParameterToNode(p *psuedochecker.PsuedoParameter
206223 nil ,
207224 )
208225}
226+
227+ func (b * nodeBuilderImpl ) psuedoTypeToType (t * psuedochecker.PsuedoType ) * Type {
228+ // !!! TODO: only literal types currently mapped because this is only used to determine if literal contextual typing need apply to the psuedotype
229+ // If this is used more broadly, the implementation needs to be filled out more to handle the structural psuedotypes - signatures, objects, tuples, etc
230+ debug .Assert (t != nil , "Attempted to realize nil psuedotype" )
231+ switch t .Kind {
232+ case psuedochecker .PsuedoTypeKindDirect :
233+ return b .ch .getTypeFromTypeNode (t .Data .(* psuedochecker.PsuedoTypeDirect ).TypeNode )
234+ case psuedochecker .PsuedoTypeKindInferred :
235+ node := t .Data .(* psuedochecker.PsuedoTypeInferred ).Expression
236+ ty := b .ch .getTypeOfExpression (node )
237+ return ty
238+ case psuedochecker .PsuedoTypeKindNoResult :
239+ return nil // TODO: extract type selection logic from `serializeTypeForDeclaration`, not needed for current usecases but needed if completeness becomes required
240+ case psuedochecker .PsuedoTypeKindMaybeConstLocation :
241+ d := t .Data .(* psuedochecker.PsuedoTypeMaybeConstLocation )
242+ return b .psuedoTypeToType (d .ConstType ) // !!! TODO: not needed for const-checking usecases, but proper context switching behavior required if completeness is required
243+ case psuedochecker .PsuedoTypeKindUnion :
244+ var res []* Type
245+ var hasElidedType bool
246+ members := t .Data .(* psuedochecker.PsuedoTypeUnion ).Types
247+ for _ , m := range members {
248+ if ! b .ch .strictNullChecks {
249+ if m .Kind == psuedochecker .PsuedoTypeKindUndefined || m .Kind == psuedochecker .PsuedoTypeKindNull {
250+ hasElidedType = true
251+ continue
252+ }
253+ }
254+ t := b .psuedoTypeToType (m )
255+ if t == nil {
256+ return nil // propagate failure
257+ }
258+ res = append (res , t )
259+ }
260+ if len (res ) == 1 {
261+ return res [0 ]
262+ }
263+ if len (res ) == 0 {
264+ if hasElidedType {
265+ return b .ch .anyType
266+ }
267+ return b .ch .neverType
268+ }
269+ return b .ch .newUnionType (ObjectFlagsNone , res )
270+ case psuedochecker .PsuedoTypeKindUndefined :
271+ return b .ch .undefinedWideningType
272+ case psuedochecker .PsuedoTypeKindNull :
273+ return b .ch .nullWideningType
274+ case psuedochecker .PsuedoTypeKindAny :
275+ return b .ch .anyType
276+ case psuedochecker .PsuedoTypeKindString :
277+ return b .ch .stringType
278+ case psuedochecker .PsuedoTypeKindNumber :
279+ return b .ch .numberType
280+ case psuedochecker .PsuedoTypeKindBigInt :
281+ return b .ch .bigintType
282+ case psuedochecker .PsuedoTypeKindBoolean :
283+ return b .ch .booleanType
284+ case psuedochecker .PsuedoTypeKindFalse :
285+ return b .ch .falseType
286+ case psuedochecker .PsuedoTypeKindTrue :
287+ return b .ch .trueType
288+ case psuedochecker .PsuedoTypeKindStringLiteral , psuedochecker .PsuedoTypeKindNumericLiteral , psuedochecker .PsuedoTypeKindBigIntLiteral :
289+ source := t .Data .(* psuedochecker.PsuedoTypeLiteral ).Node
290+ return b .ch .getTypeOfExpression (source ) // big shortcut, uses cached expression types where possible
291+ default :
292+ return nil
293+ }
294+ }
0 commit comments