question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Global TypeScript interface type for easy extension of model typings

See original GitHub issue

Currently configuring the model typings of an app usually requires going through the typegenAutoConfig.backingTypeMap. This can be cumbersome. Especially for small ad-hoc changes. Another method could be offered to users that might serve some use-cases better. The idea would be a global interface type which can then be extended and once so, would be reflected in the map typings across the codebase.

The example below uses the new proposed model typings api (#583).

Example:

declare global {
 interface NexusModels {
   Foo: {
     a: string
     b: number
   }
 }
}

objectType({
  name: "Thing",
  modelTyping: "Foo",
  definition(t) {
    t.field('qux', {
      resolve(foo) {
        foo.a.toLowerCase() // type checks
        foo.b.toFixed() // type checks
      }
    })
  }
})

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:10 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
jasonkuhrtcommented, Oct 30, 2020

@Weakky and I talked about this today. We decided that the lack of type safety (e.g. typos) when populating:

declare global { interface NexusModels { ... } }

is a significant problem. We decided to keep this in discussion phase for longer before implementing.

Meanwhile there are other potential solutions for making model type maps easier to work with in Nexus.

We’ll try to post a summary post soon, maybe as a new broad issue called “make model type mapping easier”.

1reaction
Naynicommented, Oct 30, 2020

I like the idea of having the backing type map and sources more in user land. However I’d like to show an example of why I would be against removing sources in their current state.

In most of the projects I work on I try to strive for convention over configuration. One of the ways this manifests is that I advocate for strong conventions around files and folders. An example of such a convention is that it should be clear where database or domain models are coming from.

A real example of a project I work on is the following:

  • The project domain is divided into clear module boundaries: users, posts, likes (not giving real domain names here but you get the gist I hope)
  • Domain or database entities have a file name convention, they end with Entity. This makes for a very visual clue when looking up entities.

Having these two conventions in place, wiring up Nexus for the 90% use-case is trivial, we have 1 function which does all of it based on file conventions:

/**
 * Search all modules for possible Entities
 * (based on file convention, files that contain entities should end with Entity).
 * For all these entities it creates a typegen source for Nexus to inject.
 */
function getEntitySources() {
  const modules = findModuleDirectories();
  return modules
    .flatMap(m => fs.readdirSync(m).map(f => path.join(m, f)))
    .filter(f => fs.statSync(f).isFile() && ENTITY_FILE_REGEX.test(f))
    .map((f, i) => {
      return {
        source: f,
        alias: (
          ENTITY_FILE_REGEX.exec(f)?.groups?.entity || `entity${i})`
        ).toLowerCase(),
      };
    });
}

This auto wires up any entity that is created as a possible backing type for Nexus to match on. Allowing anyone to introduce a new entity without having to worry about schema config.

The global interface would be nice for our use-case but only solves for those 10% edge cases we wire up manually…

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handbook - Interfaces - TypeScript
One of TypeScript's core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or...
Read more >
Extending object-like types with interfaces in TypeScript
Extending object-like types with interfaces in TypeScript · Option 1: Declaration merging · Declaration merging to wrangle disparate user ...
Read more >
Extending global types (e.g. "Window") inside a typescript ...
Yes, you just need to wrap the interface into global declaration: declare global { interface Window { myCounter: number; } }. Global scope...
Read more >
A Simple Guide to Typescript Interfaces: declaration & use cases
In TypeScript, an interface is an abstract type that tells the compiler which property names a given object can have. TypeScript creates ...
Read more >
Working with JavaScript in Visual Studio Code
IntelliSense for JavaScript libraries and frameworks is powered by TypeScript type declaration (typings) files. Type declaration files are written in ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found