@@ -540,8 +540,9 @@ const printError = (diagnostic) => {
540540 /** @typedef {{ type: "index", symbolName: SymbolName, objectType: ts.Type, indexType: ts.Type } } ParsedIndexType */
541541 /** @typedef {{ type: "template", texts: readonly string[], types: readonly ts.Type[] } } ParsedTemplateType */
542542 /** @typedef {{ type: "import", symbolName: SymbolName, exportName: string, from: string, isValue: boolean } } ParsedImportType */
543- /** @typedef {{ type: "symbol", symbolName: SymbolName } } ParsedSymbolType */
544- /** @typedef {ParsedPrimitiveType | ParsedTypeParameterType | ParsedTupleType | ParsedInterfaceType | ParsedReferenceType | ParsedUnionType | ParsedIntersectionType | ParsedIndexType | ParsedTemplateType | ParsedImportType | ParsedSymbolType } ParsedType */
543+ /** @typedef {{ type: "symbol", symbolName: SymbolName} } ParsedSymbolType */
544+ /** @typedef {{ type: "conditional", symbolName: SymbolName, checkType: ts.Type, extendsType: ts.Type, trueType: ts.Type, falseType: ts.Type, typeParameters?: readonly ts.Type[] } } ParsedConditionalType */
545+ /** @typedef {ParsedPrimitiveType | ParsedTypeParameterType | ParsedTupleType | ParsedInterfaceType | ParsedReferenceType | ParsedUnionType | ParsedIntersectionType | ParsedIndexType | ParsedTemplateType | ParsedImportType | ParsedSymbolType | ParsedConditionalType } ParsedType */
545546 /** @typedef {ParsedType | MergedClassType | MergedNamespaceType } MergedType */
546547
547548 const isExcluded = ( name ) => {
@@ -848,6 +849,8 @@ const printError = (diagnostic) => {
848849 return argsWithoutDefaults ;
849850 } ;
850851
852+ const symbol = type . aliasSymbol || type . getSymbol ( ) ;
853+
851854 if ( /** @type {any } */ ( type ) . isTypeParameter ( ) ) {
852855 return {
853856 type : "typeParameter" ,
@@ -1053,8 +1056,6 @@ const printError = (diagnostic) => {
10531056 } ;
10541057 }
10551058
1056- const symbol = type . aliasSymbol || type . getSymbol ( ) ;
1057-
10581059 if ( objectFlags & ts . ObjectFlags . Reference ) {
10591060 const typeRef = /** @type {ts.TypeReference } */ ( type ) ;
10601061 const typeArguments = checker . getTypeArguments ( typeRef ) ;
@@ -1200,6 +1201,38 @@ const printError = (diagnostic) => {
12001201 } ;
12011202 }
12021203
1204+ if ( flags & ts . TypeFlags . Conditional ) {
1205+ const { checkType, extendsType, root } =
1206+ /** @type {ts.ConditionalType } */ ( type ) ;
1207+
1208+ return {
1209+ type : "conditional" ,
1210+ symbolName,
1211+ checkType,
1212+ extendsType,
1213+ trueType : checker . getTypeAtLocation ( root . node . trueType ) ,
1214+ falseType : checker . getTypeAtLocation ( root . node . falseType ) ,
1215+ typeParameters :
1216+ type . aliasTypeArguments && type . aliasTypeArguments . length > 0
1217+ ? type . aliasTypeArguments
1218+ : undefined ,
1219+ // skip: true,
1220+ } ;
1221+ }
1222+
1223+ if ( flags & ts . TypeFlags . IndexedAccess ) {
1224+ const { objectType, indexType } = /** @type {ts.IndexedAccessType } */ (
1225+ type
1226+ ) ;
1227+
1228+ return {
1229+ type : "index" ,
1230+ symbolName : parseName ( type ) ,
1231+ objectType,
1232+ indexType,
1233+ } ;
1234+ }
1235+
12031236 const declaration = getDeclaration ( symbol ) ;
12041237
12051238 return {
@@ -1289,6 +1322,12 @@ const printError = (diagnostic) => {
12891322 captureType ( type , inner ) ;
12901323 }
12911324 break ;
1325+ case "conditional" :
1326+ captureType ( type , parsed . checkType ) ;
1327+ captureType ( type , parsed . extendsType ) ;
1328+ captureType ( type , parsed . trueType ) ;
1329+ captureType ( type , parsed . falseType ) ;
1330+ break ;
12921331 case "interface" :
12931332 for ( const prop of parsed . baseTypes ) {
12941333 typeUsedAsBaseType . add ( prop ) ;
@@ -1651,6 +1690,18 @@ const printError = (diagnostic) => {
16511690 return x === undefined ? item : x ;
16521691 } ) ;
16531692 }
1693+ case "conditional" : {
1694+ const { symbolName, checkType, extendsType, trueType, falseType } =
1695+ parsed ;
1696+ return [
1697+ parsed . type ,
1698+ symbolName [ 0 ] ,
1699+ checkType ,
1700+ extendsType ,
1701+ trueType ,
1702+ falseType ,
1703+ ] ;
1704+ }
16541705 case "interface" : {
16551706 const {
16561707 symbolName,
@@ -1770,6 +1821,12 @@ const printError = (diagnostic) => {
17701821 const needName = [ ] ;
17711822 for ( const [ type , parsed ] of parsedCollectedTypes ) {
17721823 switch ( parsed . type ) {
1824+ case "conditional" : {
1825+ if ( parsed . typeParameters ) {
1826+ needName . push ( [ type , parsed ] ) ;
1827+ }
1828+ break ;
1829+ }
17731830 case "interface" : {
17741831 if (
17751832 parsed . typeParameters ||
@@ -2157,6 +2214,7 @@ const printError = (diagnostic) => {
21572214 return parsed . name ;
21582215 case "typeParameter" : {
21592216 let code = parsed . name ;
2217+
21602218 if ( state === "in type args" ) {
21612219 if ( parsed . constraint ) {
21622220 const constraint = getCode ( parsed . constraint , typeArgs , state ) ;
@@ -2167,6 +2225,7 @@ const printError = (diagnostic) => {
21672225 code += ` = ${ defaultValue } ` ;
21682226 }
21692227 }
2228+
21702229 return code ;
21712230 }
21722231 case "template" : {
@@ -2180,10 +2239,21 @@ const printError = (diagnostic) => {
21802239 return code ;
21812240 }
21822241 case "index" : {
2183- return `(${ getCode ( parsed . objectType , typeArgs ) } )[${ getCode (
2184- parsed . indexType ,
2185- typeArgs ,
2186- ) } ]`;
2242+ const { objectType, indexType } = parsed ;
2243+ const getIndexTypeCode = ( ) => {
2244+ if ( indexType . flags & ts . TypeFlags . Substitution ) {
2245+ const { baseType } = /** @type {ts.SubstitutionType } */ ( indexType ) ;
2246+ const symbol = baseType . getSymbol ( ) ;
2247+ if ( symbol ) {
2248+ const name = symbol . getName ( ) ;
2249+ if ( name !== "__type" && name !== "unknown" ) return name ;
2250+ }
2251+ }
2252+
2253+ return getCode ( indexType , typeArgs ) ;
2254+ } ;
2255+
2256+ return `(${ getCode ( objectType , typeArgs ) } )[${ getIndexTypeCode ( ) } ]` ;
21872257 }
21882258 case "union" :
21892259 case "intersection" : {
@@ -2261,6 +2331,59 @@ const printError = (diagnostic) => {
22612331 "with type args" ,
22622332 ) } ${ typeArgumentsWithoutDefaults } `;
22632333 }
2334+ case "conditional" : {
2335+ const getExtendsString = ( t ) => {
2336+ if ( t . flags & ts . TypeFlags . TypeParameter ) {
2337+ const symbol = t . getSymbol ( ) ;
2338+ if (
2339+ symbol &&
2340+ symbol . declarations &&
2341+ symbol . declarations . length > 0
2342+ ) {
2343+ const decl = symbol . declarations [ 0 ] ;
2344+ if (
2345+ ts . isTypeParameterDeclaration ( decl ) &&
2346+ decl . parent &&
2347+ ts . isInferTypeNode ( decl . parent )
2348+ ) {
2349+ return "infer " + symbol . getName ( ) ;
2350+ }
2351+ }
2352+ return symbol ? symbol . getName ( ) : getCode ( t , typeArgs , state ) ;
2353+ }
2354+
2355+ if ( checker . isArrayType ( t ) ) {
2356+ const elementType = t . typeArguments [ 0 ] ;
2357+ return "(" + getExtendsString ( elementType ) + ")[]" ;
2358+ }
2359+
2360+ return getCode ( t , typeArgs , state ) ;
2361+ } ;
2362+
2363+ const checkType = getCode ( parsed . checkType , typeArgs , state ) ;
2364+ const extendsType = getExtendsString ( parsed . extendsType ) ;
2365+ const trueType = getCode ( parsed . trueType , typeArgs , state ) ;
2366+ const falseType = getCode ( parsed . falseType , typeArgs , state ) ;
2367+
2368+ const variable = typeToVariable . get ( type ) ;
2369+ if ( variable !== undefined ) {
2370+ queueDeclaration (
2371+ type ,
2372+ variable ,
2373+ ( ) =>
2374+ `type ${ variable } ${
2375+ parsed . typeParameters
2376+ ? `<${ parsed . typeParameters
2377+ . map ( ( t ) => getCode ( t , new Set ( ) , "in type args" ) )
2378+ . join ( ", " ) } >`
2379+ : ""
2380+ } = (${ checkType } extends ${ extendsType } ? ${ trueType } : ${ falseType } );`,
2381+ ) ;
2382+ return `${ variable } ` ;
2383+ }
2384+
2385+ return `(${ checkType } extends ${ extendsType } ? ${ trueType } : ${ falseType } )` ;
2386+ }
22642387 case "interface" : {
22652388 const variable = typeToVariable . get ( type ) ;
22662389 if ( variable !== undefined ) {
0 commit comments