Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Template Literal Types in TS 4.1 #158

Open
acro5piano opened this issue Sep 29, 2020 · 5 comments
Open

Use Template Literal Types in TS 4.1 #158

acro5piano opened this issue Sep 29, 2020 · 5 comments

Comments

@acro5piano
Copy link
Owner

acro5piano commented Sep 29, 2020

In the following repository, it parses SQL into TypeScript type. No codegen tool is needed anymore.

https://github.com/codemix/ts-sql

The syntax should be like this:

// Query.ts

import { QueryFactory } from 'typed-graphqlify'

const schema = gql`
  type Query { 
    hello: String!
  }
`

export type Query<T> = QueryFactory<T, typeof schema>
// HelloQuery.ts

import { Query } from './Query'

const HelloQuery = gql`
  { hello }
`

type IHelloQuery = Query<typeof query>

// Equivalent to the following. Cool!
//
// type IHelloQuery = {
//   data?: { 
//     hello: string
//   }
// }

I think we can do the same thing in GrapQL.

I've started to work on this, will use next branch.

@acro5piano
Copy link
Owner Author

Seems that it uses the new feature Template Literal Types which will be out in TypeScript 4.1.

https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types

@acro5piano acro5piano changed the title Get type from string? Use Template Literal Types in TS 4.1 Sep 29, 2020
@acro5piano
Copy link
Owner Author

This repository should be checked.

https://github.com/dotansimha/graphql-typed-ast

@acro5piano
Copy link
Owner Author

acro5piano commented Sep 29, 2020

I've figured out prototype! I'll try on this.

/*
 * TypeScript 4.1
 */

type GetSchema<Schema> =
  Schema extends `type Query { ${infer RootQueryName}: String! }`
    ? { [k in RootQueryName]: string }
    : never

type QueryBuilder<Schema, Query> = Query extends `{ ${infer RootQueryName} }`
  ? RootQueryName extends keyof Schema ? { [k in RootQueryName]: Schema[RootQueryName] } : never
  : never

type Schema = GetSchema<`type Query { hello: String! }`>

type ExpectQueryType = QueryBuilder<Schema, '{ hello }'> // => { hello: string }
type ExpectNever = QueryBuilder<Schema, '{ foo }'> // => never

As Expression produces a union type that is too complex to represent., there must be some limitation.

image

@acro5piano
Copy link
Owner Author

@acro5piano
Copy link
Owner Author

acro5piano commented Oct 17, 2020

It turns out to be difficult for the current TypeScript type's performance. see: dotansimha/graphql-typed-ast#2 (comment)

Instead, how about implement "minimal overhead" syntax??

mutation updateUserMutation($input: UserInput!) {
  updateUser(input: $input) {
    id
    name
    bankAccounts {
      id
    }
  }
}

Common API:

MUTATION.toString() // => print query
MUTATION.dataType() // => returns data type
MUTATION.variableType() // => returns variable type
  1. aggressive (maybe with some codegen tool)
import { mutation, f } from 'typed-graphqlify'

const MUTATION = mutation('updateUserMutation($input: UserInput!)', {
  ['updateUser(input: $input)']: f(
    'id',
    'name',
    f('bankAccounts', f({
      'id',
    })),
  `,
})
  1. moderate (similar to v2 format)
import { input, mutation, f, types } from 'typed-graphqlify'

const UserInput = input('UserInput', {
  name: types.string,
})

const MUTATION = mutation(`updateUserMutation($input: ${UserInput})`, {
  ['updateUser(input: $input)']: {
    id: types.string,
    name: types.string,
    bankAccounts: {
      id: types.string,
    }
  },
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant