#Circular type aliases

37 messages · Page 1 of 1 (latest)

winter steppeBOT
#
piscopancer#0

Preview:```ts
interface Humans {
inna: typeof inna
bob: typeof bob
}

type Human = Humans[keyof Humans]
type HumanName = Human["name"]

type HumanBase = {
name: string
parent: HumanName
}

function createHuman<H extends HumanBase>(human: H) {
return human
...```

quaint nymph
#

I want to human inna to reference inna, the logic is - if a person inna was ever created, it means such name exists, so her mother or a child can be called inna too

#

it lays normally in my head, but TS does not let types reference themselves, how is it different from self-referencing?

grand gull
#

this doesn't really make sense to have in type-space

quaint nymph
#

i tried to reproduce my complicated error from my project using humans

#

or wdym

grand gull
#

you're trying to have a kind of stateful registration, but types are kinda stateless

quaint nymph
#

i am making a lib and i wanted to do it the way Tiptap devs do it

#

somehow they don't have such an error

grand gull
#

right, that's with declaration merging

#

you don't have declaration merging

quaint nymph
#

:[

grand gull
#

i don't think that's exactly the issue though

quaint nymph
#

yes, i removed declaration merging from the humans example

#

it's not the issue

#

the issue is circular types

#

which i almost understand

grand gull
#

we can reduce the example further

winter steppeBOT
#
that_guy977#0

Preview:```ts
interface Humans {
inna: typeof inna;
}

type HumanBase = {
name: string;
parent: Humans[keyof Humans];
};

const inna = {
name: "inna",
parent: null,
// ^?
} satisfies HumanBase```

grand gull
#

inna is a HumanBase.
HumanBase.parent is a value of Humans, aka typeof inna
inna needs to know about typeof inna before it can type parent

quaint nymph
#

damn that's deep

#

though that's exactly the behavior i wanted

grand gull
#

we can get even simpler

#

i shouldve named those better one sec

winter steppeBOT
#
that_guy977#0

Preview:ts type X = { k: typeof x } const x = { k: null //^? } satisfies X

grand gull
#

x needs to know about X.k
X.k needs to know about x

quaint nymph
#

i see

#

i have to change my approach

grand gull
#

i don't think the tiptap example you brought up has any circular references, does it?

quaint nymph
#

it does not

#

I can think of some ways to solve this but they all seem to have circular deps issue bcs that's exactly how i want it

#

gosh i might be able to split something to help TS

#

my current approach is to do it manually, type here is alternative to the name from humans example

declare module '@repo/studio' {
  interface CustomDocumentDefinitions {
    shop: { type: 'shop' }
    employee: { type: 'employee' }
  }
}
#

so i am going with some manual labor

#

this way i can reference document by its type from within its own definition

export const shopDefinition = defineDocument({
  type: 'shop',
  fields: {
    director: defineReference({
      to: ['employee'],
    }),
    closestShop: defineReference({
      to: ['shop'],
    }),
#

basically I just helped TS by hand

#

gonna mark it with resolved bcs i think TS will not let me have circular dependencies anyways