Skip to content

Recursive Type Field Validation + Suggest, compile, fail over, Improve Transform of Circular Types Generic type hint Circular<type> #61685

Closed as not planned
@wesleyolis

Description

@wesleyolis

🔎 Search Terms

Recursive Type, Recursive Type Definition, then some auto suggest, but nothing matched.

🕗 Version & Regression Information

Recursive Type Definition, few other field evaluation for assignment fails, but does correctly evaluate initialization of objects to a degree, feel there issue there still.

Latest v5.9.0-dev.20250511 doens't work
https://www.typescriptlang.org/play/?ts=5.0.4
Seems to be in 3,4 as well, been a while back on the sense pushing things again TS language.

https://www.typescriptlang.org/play/?ts=3.3.3#code/FASwdgLgpgTgZgQwMZQARIPYzQb2K1BALlTAFcBbAI1gBp9UqSBnCGcAc2AF9hRJYiFKgDCqPAQAmJctToMkLNpx59gEAJ4AHNAAURAQV0BJAEpQ4IkDCRkANghioAvAUzZUAMnENmZKiII0BxYGiSoABRiAD6o+kZmFlY29o4AlADaALoA3Dx56tp6hibmcMYAIi5xJYmW1rYOMAWYYKyo0Kwk8aUWlfiuEsQAjPSMRADknRATY34BQVAhMGGoGQwSBIREowwETBPMknCzDAD0ZwTMR3CTs6gXqACiMDBYqAAWCGCSdpyoIGYqAA7lgANacAB0e1Q80CwVCJHWWy2mxRUh2Y3Rj1hx2uxzutAelxebycAAlvr9-oCQeCoTCUYoJqd0QRHjdJjd7o9Se9KT8-mAOACgaCYBDhdC2Vd-PClojsozULwUVkGKr1dwChdppC4YtlhoMgAGLKQ4kERAgOxAiAYQhke2wsgcDhQVhQSR8VrtaYIa4gDhgL3VPUGhErU25YC+iAdD0QAPMIMhyS6N5aMOJ5Op0MAQlc5DsdlQAH4E6xc8GvZCqKgSCycpbrbaOg7MBQdNBYxg2vH-YGa+nMwAhbNVodpst15uPVt2jsYLs2qBAA

Example: When testing the type validation upon validation recursive instantiation of an object, all works find by the looks of things, the compiler picks up invalid keys.

interface core {
  a: number,
  b: string
}

interface C {
  d: number,
  c: string
}


type PCAPIRefCircular =  core & {
  subCategory:  (C | PCAPIRefCircular)[];
};

type PCAPIRefID = PCAPIRefCircular;

const test: PCAPIRefID
 = {
 a:1,
 b:'test',
 subCategory: [
  {
    a:1,
    b:'sdf',
  //  ssdf:'', // Error handling is working.
    subCategory: [
      {
        d:1,
      //  sdfssdf:'', // Error Handling is working.
        c:'',
       // sdf:'sdf', // Error Handling is working.
        subCategory:[]
      }
    ]
  }
 ]
};

//test.subCategory[0]. //  fails to auto suggested

const testassigned = test.subCategory[0];
const testassignedProp = testassigned != null ? testassigned.b : ''; // fails to compete
const testassignedPropB = testassigned?.b; // fails to compile

⏯ Playground Link

No response

💻 Code

interface core {
  a: number,
  b: string
}

interface C {
  d: number,
  c: string
}


type PCAPIRefCircular =  core & {
  subCategory:  (C | PCAPIRefCircular)[];
};

type PCAPIRefID = PCAPIRefCircular;

const test: PCAPIRefID
 = {
 a:1,
 b:'test',
 subCategory: [
  {
    a:1,
    b:'sdf',
  //  ssdf:'', // Error handling is working.
    subCategory: [
      {
        d:1,
      //  sdfssdf:'', // Error Handling is working.
        c:'',
       // sdf:'sdf', // Error Handling is working.
        subCategory:[]
      }
    ]
  }
 ]
};

//test.subCategory[0]. //  fails to auto suggested

const testassigned = test.subCategory[0];
const testassignedProp = testassigned != null ? testassigned.b : ''; // fails to compete
const testassignedPropB = testassigned?.b; // fails to compile

🙁 Actual behavior

It should have been able to auto suggestion both of the union structures and it should have then based
on the first unique appearing field form one of the union structures in the subsCategory fields,
been able to narrow down the type to the correct union type, against which to validate everything.

🙂 Expected behavior

I expect that auto suggest both the union structures and that it validates it against the one with the most matching fields with union definition.

I would also expect and know that you can internally should have been able to evaluate the reclusive type for the next level of iteration for the keys, that could have been chosen by evaluation the reclusive type by excluding its self reference logically. You could have implemented lazy evaluation. upon the key being expanded for subcategory, then you could upon what typed in for subcategory again, know which type was chosen and evaluate it again.

Additional information about the issue

The generic form of this also needs to work as well.
`.ts
type PCAPIRefCircular<TCore extends Record<any,any>,TRef extends Record<any,any>> = TCore & {
subCategory: (TRef | PCAPIRefCircular)[];
};

type PCAPIBoth = PCAPIRefCircular<PCAPIRefID | PCAPIRefEmbeded | PCAPIRefEmbededBoth >
`

As for reclusive type definition your hard code limit, that AWS with Amplify Relationships, triggers at 50 and apret from their types all fail for ReturnType, which makes things crazy difficult, but then wonder for some of the stuff if they understood Log(n) algorithms, as hang everything in the IDE at times crashes engine that have to crash delete issues types, crash vscode again, then be fine as engine fee buggy type removed form the engine, impossible to use there framework for alot of things and its like V6 of this.
https://github.com/wesleyolis/mongooseRelationalTypes - 2018 already with tung of tables and fields, compare what we have now and impossible to work, I had hack and deep dive there types to fix it., We had better suggestive types that program with compare to amplify and types from the db, aws returns undefined instead of null in many places also didn't get all the permutations correct to work with dbs, readonly, null, optional, default, and at db or dbwrapper level, who the drive default, it it force, few more permutations, then relationships. ...

So to the point, you can when evaluating reclusive types for validation, have 2 requirements in your engine,
The recursive type and actually physical object to validate. You perform recursive validation as long the object has keys and then stop, this happens if still does, as par ts 2, 3 I wrote generics that selft expansion validating.

Transform of Circular Types Generic type hint Circular
If it was recursive type and inspection or transform of another type, like alot more things, you can detect recursive type and take the approach above that I suggested, to get the next set of keys in the engine and then stop and place reference to transform recursive type definition, which should permanently solve your problem of infinite evaluation, because detect recursive types and transform them into new recursive types.
So introduce a new special type that inject in the compiler for recursive place holder.
Alternative instead having to monitor type names in dictionary for circular reference as you expaned.
could made introduce a new syntax, i.e type = NameOfType = {a:any, b:any, c: Circular

Implicitly you then add Circular reference types to a stack dictionary only for those which have the Circular generic wrapper notation, to speed up and reduce the computation overhead of detecting circular types.
You can then transform circular types and keep them circular avoiding the 50 level depth iteration problem.
But then again AWS evaluates array of setRelationships with everything, which is NXN transform and not ideal, instead of Log(n), hope they apply some algorithmic thinking next time to there types. then these operation times few how may times use, it as there no caching of single concrete reference.

Guess on could look at export wrapper take a snap shot, else need implemented SnapCacheType<> generic Hints to the compiler to speed things up after which could reset the 50 iteration limit again.

Look forward to see the improvement in support for Transforms Circular References to new types of that are still Circular References.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions