美文网首页
【超详细】如何使用TypeScript和GraphQL开发应用

【超详细】如何使用TypeScript和GraphQL开发应用

作者: 编程范儿 | 来源:发表于2021-01-29 12:19 被阅读0次

    GraphQL是一个专为构建灵活的API而生的强大的查询语言。它允许您为数据定义类型系统,因此在执行查询时,它仅返回所需的数据。

    与TypeScript一起使用时,GraphQL可以为开发人员提供更好的体验,因为它们都是类型语言。 TypeScript是JavaScript的类型化超集,可通过添加类型对其进行扩展。 因此,一起使用这些技术肯定会帮助您构建可预测的强类型API。

    在本教程中,我将首先解释为什么要结合这些技术,然后通过使用TypeGraphQL从头构建API来展示如何将TypeScript与GraphQL结合使用。

    先决条件

    本教程假定您有使用TypeScript的经验,尤其是对TypeScript类和装饰器。 GraphQL的知识将派上用场,但不是强制性的。

    在本指南中,我们将使用TypeGraphQL
    ,这是一个使用Node.js和TypeScript构建GraphQL API的现代框架。

    为什么将TypeScript与GraphQL一起使用

    TypeScript是由Microsoft开发和维护的一种流行编程语言。 它是JavaScript的超集,它使用静态类型检查使代码可预测。

    多年来,TypeScript已被证明是用于大型代码库的有价值的语言。 TypeScript通过其类型来提高代码质量,从而增加代码的健壮性,可理解性和可预测性。

    GraphQL解决了API过度获取或获取不足的问题。 GraphQL 可以通过一次请求就获取你应用所需的所有数据。 通过这种方式,GraphQL使您的查询变得灵活,并且您的API可读且易于学习。

    TypeScript和GraphQL都依靠类型使代码易于理解。但是,只能使用buildSchema方法或扩展名为.gql的文件在GraphQL模式中定义GraphQL类型。 GraphQL解析器不支持GraphQL类型,因为解析器只是常规的JavaScript函数,而不是GraphQL代码。 TypeScript解决了这个问题,因为正如我们前面提到的那样,它是JavaScript的超集。因此,它可以在GraphQL解析器上设置类型。这就是为什么将TypeScript与GraphQL一起使用才有意义的原因。

    GraphQL处理GraphQL模式的类型,而TypeScript设置GraphQL解析器上的类型。但是,由于要处理多种语言,因此使用Node.js,GraphQL和TypeScript构建强类型的API可能很难维护。

    TypeGraphQL打算解决保持模式与解析器之间一致性的问题。 TypeGraphQL允许您使用TypeScript类和装饰器来为API创建架构,类型和解析器。它使用TypeScript构建整个GraphQL API。

    到目前为止,我们已经了解了为什么将TypeScript与GraphQL搭配一起使用,以及为什么TypeGraphQL在构建和维护使用TypeScript版GraphQL API时很方便。

    事不宜迟,让我们深入练习部分,并使用TypeGraphQL构建GraphQL API。

    安装

    在使用TypeScript和GraphQL之前,我们首先得创建一个Node.js的应用,打开你的终端界面,执行以下命令:

    yarn init
    

    或者使用npm包管理器

    npm init
    

    然后需要你为项目设定一些信息,不需要填的一路回车就好,最后会在项目目录生成package.json文件。

    fantingshengdeMacBook-Pro:graphql-typescript fantingsheng$ yarn init
    yarn init v1.12.3
    question name (graphql-typescript):
    question version (1.0.0):
    question description: for study
    question entry point (index.js):
    question repository url: https://github.com/fantingsheng/graphql-typescript
    question author: Timfan
    question license (MIT):
    question private:
    success Saved package.json
    ✨  Done in 223.35s.
    

    接下来安装一些需要的依赖

    yarn add express apollo-server-express graphql reflect-metadata type-graphql class-validator
    

    或者

    npm install express apollo-server-express graphql reflect-metadata type-graphql class-validator
    

    我们先下载好这些安装包,然后再解释它们分别是干什么的。另外还要安装它们的类型定义,以便支持TypeScript的使用。

    yarn add -D ts-node typescript @types/express @types/node nodemon
    

    或者

    npm install -D ts-node typescript @types/express @types/node nodemon
    

    注意:我们安装nodemon是为了在代码更新的时候热重载

    下面是每个依赖库的作用解释:

    • express是一个极简的Node版web框架
    • apollo-server-express是一个允许我们在Apollo GraphQL服务中使用express的中间件
    • reflect-metadata使得TypeScript装饰器可以在当一个类已经定义的时候为它添加一个类和成员。它是TypeGraphQL的一个依赖。
    • class-validator允许TypeGraphQL基于验证的情况下使用装饰器和非装饰器

    接下来,为项目搭建结构

    src
    | ├── resolvers
    | |  └── todoResolver.ts
    | └── schemas
    | |  └── Todo.ts
    | └── index.ts
    ├── tsconfig.json
    ├── package.json
    └── yarn.lock
    

    这里有四个文件需要说明下:

    • 应用的入口文件index.ts
    • schemas目录包含了该项目的GraphQL Schema
    • resolvers目录包含了所有API的实现
    • tsconfig.json告诉TypeScript如何去编译代码

    与此同时,我们需要在package.json文件中添加服务的执行命令:

    "scripts": {
      "start": "nodemon --exec ts-node src/index.ts"
    }
    

    该script命令通过使用nodemon去开启服务,即使代码临时修改,也会重启生效。

    为tsconfig.json文件增加配置

    {
      "compilerOptions": {
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true
      }
    }
    

    以上这两个属性都要设置为true,以便我们可以在项目中使用TypeScript的装饰器。

    我们现在可以为API创建一个GraphQL Schema了。

    创建GraphQL Schema

    TypeGraphQL使得你可以通过TypeScript的类和装饰器创建一个schema,它仅仅是语法糖而已,最终还是会生成GraphQL代码。这个稍后再说,先创建一个schema

    • schema/Todo.ts
    import { Field, ObjectType, InputType } from "type-graphql"
    
    @ObjectType() export class Todo {
      @Field() id: number
      @Field() title: string
      @Field() description: string
      @Field() status: boolean
    }
    
    @InputType() export class TodoInput implements Partial<Todo> {
      @Field() title: string
      @Field() description: string
    }
    

    乍一看这语法好像有点奇怪,其实没什么,仅仅是因为增加了TypeScript的装饰器和类的概念在里面

    这里的@ObjectType()是由TypeGraphQL提供,为了创建新的对象和schema而存在。Todo类反应了Todo对象的结构,TodoInput定义了我们往Todo里面增加的期望数据
    结构。

    如下是相同功能的GraphQL代码。

    type Todo {
      id: ID!
      title: String!
      description: String!
      status: Boolean!
    }
    
    input TodoInput {
      title: String!
      description: String!
    }
    

    可以看到逻辑完全一样,唯一的不同是没有使用TypeScript。

    创建GraphQL Resolver

    不像GraphQL,TypeGraphQL将query和mutation语句写在了resolver的里面,当被调用的时候方法名作为唯一入口。

      
    import { Query, Resolver, Mutation, Arg } from "type-graphql";
    import { Todo, TodoInput } from "../schemas/Todo";
    
    
    @Resolver(of => Todo)
    export class TodoResolver {
        private todos: Todo[] = []
    
      @Query(returns => [Todo], { nullable: true })
      async getTodos(): Promise<Todo[]> {
        return await this.todos;
      }
    
      @Mutation(returns => Todo)
      async addTodo(@Arg('todoInput') {title, description }: TodoInput): Promise<Todo> {
        const todo = {
          id: Math.random(),
          title,
          description,
          status: false
        }
    
        await this.todos.push(todo)
        return todo;
      }
    }
    

    这里我们使用resolver装饰器创建一个新的返回Todo的GraphQL resolver。然后,创建一个GraphQL query去查询所有的Todo类型的数据。

    之后,我们再定义一个mutation query往Todo类型的数组里增加一组新的数据。

    让我们把代码转化成GraphQL形式

    type Mutation {
      addTodo(todoInput: TodoInput!): Todo!
    }
    
    type Query {
      getTodos: [Todo!]
    }
    

    到这里,我们就可以通过创建好的schema和resolver来搭建服务了。

    搭建服务

    • src/index.ts
    import "reflect-metadata";
    import { ApolloServer } from "apollo-server-express";
    import * as Express from "express";
    import { buildSchema } from "type-graphql";
    
    import { TodoResolver } from "./resolvers/todoResolver";
    
    async function main() {
      const schema = await buildSchema({
        resolvers: [TodoResolver],
        emitSchemaFile: true
      });
    
      const app = Express();
    
      const server = new ApolloServer({
        schema
      });
    
      server.applyMiddleware({ app });
    
      app.listen(4000, () =>
        console.log("Server is running on http://localhost:4000/graphql")
      );
    }
    
    main();
    

    我们导入TodoResolver,通过在buildSchema方法里以resolver参数传入,这样来创建一个新的GraphQL Schema。

    然后通过schema对象来创建一个ApolloServer

    设置属性emitSchemaFile: true来允许TypeGraphQL在打包阶段生成一个schema.gql文件。

    通过以下命令来启动应用

    yarn start
    

    或者

    npm start
    

    在浏览器中访问http://localhost:4000/graphql

    在项目根目录下生成了一个schema.gql文件

    # -----------------------------------------------
    # !!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!!
    # !!!   DO NOT MODIFY THIS FILE BY YOURSELF   !!!
    # -----------------------------------------------
    
    type Mutation {
      addTodo(todoInput: TodoInput!): Todo!
    }
    
    type Query {
      getTodos: [Todo!]
    }
    
    type Todo {
      description: String!
      id: Float!
      status: Boolean!
      title: String!
    }
    
    input TodoInput {
      description: String!
      title: String!
    }
    

    然后添加以下代码到GraphQL运行器中创建一个新的Todo

    mutation {
      addTodo(todoInput: { title: "Todo 1", description: "This is my todo" }) {
        title
        description
        status
      }
    }
    

    然后使用以下GraphQL query查询新的Todo

    {
      getTodos {
        title
        description
        status
      }
    }
    

    好了,我们的功能完成了。

    我们已经实现了使用TypeScript构建GraphQL API。

    完整代码

    https://github.com/fantingsheng/graphql-typescript

    参考:

    获取更多作者文章,关注公众号太空编程

    相关文章

      网友评论

          本文标题:【超详细】如何使用TypeScript和GraphQL开发应用

          本文链接:https://www.haomeiwen.com/subject/dabzzktx.html