admin管理员组

文章数量:1022989

I am writing a library to define schemas.

Consider the following example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: string;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source> {
  [label: string]: ILinkDef<Source>
}

interface ISchemaDef<Source> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source>;
  };
}

class Schema<D extends ISchemaDef<any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D>>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Problem

OwnerLink returns the following inference:

type OwnerLink = {
  fwdCardinality: "one";
  revNamespace: "users";
  revLabel: string;
  revCardinality: "many";
}

I am really happy to have the literal values for fwdCardinality, revCardinality, etc.

However, I can't get revLabel to refine itself into it's literal value. I would love for revLabel to be 'ownedPosts'

Question

How could I get revLabel to keep the inference to it's literal argument, when possible?

Playground Link

I am writing a library to define schemas.

Consider the following example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: string;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source> {
  [label: string]: ILinkDef<Source>
}

interface ISchemaDef<Source> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source>;
  };
}

class Schema<D extends ISchemaDef<any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D>>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Problem

OwnerLink returns the following inference:

type OwnerLink = {
  fwdCardinality: "one";
  revNamespace: "users";
  revLabel: string;
  revCardinality: "many";
}

I am really happy to have the literal values for fwdCardinality, revCardinality, etc.

However, I can't get revLabel to refine itself into it's literal value. I would love for revLabel to be 'ownedPosts'

Question

How could I get revLabel to keep the inference to it's literal argument, when possible?

Playground Link

Share Improve this question asked Nov 19, 2024 at 1:52 Stepan ParunashviliStepan Parunashvili 2,8456 gold badges35 silver badges57 bronze badges 2
  • the definition of ILinkDef specifies revLabel to be just string, though. Do you want to change it to a generic? – qrsngky Commented Nov 19, 2024 at 1:55
  • I would love to change it to be generic, but I am not sure how I would then 'fill' in that generic value with what is provided in the schema – Stepan Parunashvili Commented Nov 19, 2024 at 2:01
Add a comment  | 

1 Answer 1

Reset to default 1

Your original definition of ILinkDef specifies revLabel to be just string. It can be changed to a generic, though. For example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source, T extends string = string> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: T;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source, T extends string = string> {
  [label: string]: ILinkDef<Source, T>
}

interface ISchemaDef<Source, T extends string = string> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source, T>;
  };
}

class Schema<D extends ISchemaDef<any, any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D, T>, T extends string = string>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Playground Link

I am writing a library to define schemas.

Consider the following example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: string;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source> {
  [label: string]: ILinkDef<Source>
}

interface ISchemaDef<Source> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source>;
  };
}

class Schema<D extends ISchemaDef<any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D>>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Problem

OwnerLink returns the following inference:

type OwnerLink = {
  fwdCardinality: "one";
  revNamespace: "users";
  revLabel: string;
  revCardinality: "many";
}

I am really happy to have the literal values for fwdCardinality, revCardinality, etc.

However, I can't get revLabel to refine itself into it's literal value. I would love for revLabel to be 'ownedPosts'

Question

How could I get revLabel to keep the inference to it's literal argument, when possible?

Playground Link

I am writing a library to define schemas.

Consider the following example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: string;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source> {
  [label: string]: ILinkDef<Source>
}

interface ISchemaDef<Source> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source>;
  };
}

class Schema<D extends ISchemaDef<any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D>>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Problem

OwnerLink returns the following inference:

type OwnerLink = {
  fwdCardinality: "one";
  revNamespace: "users";
  revLabel: string;
  revCardinality: "many";
}

I am really happy to have the literal values for fwdCardinality, revCardinality, etc.

However, I can't get revLabel to refine itself into it's literal value. I would love for revLabel to be 'ownedPosts'

Question

How could I get revLabel to keep the inference to it's literal argument, when possible?

Playground Link

Share Improve this question asked Nov 19, 2024 at 1:52 Stepan ParunashviliStepan Parunashvili 2,8456 gold badges35 silver badges57 bronze badges 2
  • the definition of ILinkDef specifies revLabel to be just string, though. Do you want to change it to a generic? – qrsngky Commented Nov 19, 2024 at 1:55
  • I would love to change it to be generic, but I am not sure how I would then 'fill' in that generic value with what is provided in the schema – Stepan Parunashvili Commented Nov 19, 2024 at 2:01
Add a comment  | 

1 Answer 1

Reset to default 1

Your original definition of ILinkDef specifies revLabel to be just string. It can be changed to a generic, though. For example:

type Cardinality = 'many' | 'one';

type ValueType = 'string' | 'number';

interface ILinkDef<Source, T extends string = string> {
  fwdCardinality: Cardinality;
  revNamespace: keyof Source;
  revCardinality: Cardinality;
  revLabel: T;
}

interface IAttrsDef {
  [label: string]: ValueType
}

interface ILinksDef<Source, T extends string = string> {
  [label: string]: ILinkDef<Source, T>
}

interface ISchemaDef<Source, T extends string = string> {
  [table: string]: {
    attrs: IAttrsDef;
    links: ILinksDef<Source, T>;
  };
}

class Schema<D extends ISchemaDef<any, any>> {
  defs: D
  constructor(
    defs: D,
  ) {
    this.defs = defs
  }
}

function schema<D extends ISchemaDef<D, T>, T extends string = string>(defs: D) {
  return new Schema<D>(defs);
}

const s = schema({
  posts: {
    attrs: {
      title: 'string'
    },
    links: {
      owner: {
        fwdCardinality: 'one',
        revNamespace: 'users',
        revLabel: 'ownedPosts', 
        revCardinality: 'many'
      }      
    }
  },
  users: {
    attrs: {
      email: 'string'
    },
    links: {}
  }
})

type OwnerLink = typeof s.defs.posts.links.owner

Playground Link

本文标签: