如何描述嵌套对象的类型?如何描述联合类型?

Posted

技术标签:

【中文标题】如何描述嵌套对象的类型?如何描述联合类型?【英文标题】:How to descibe type for nested object ? How to Describe union types? 【发布时间】:2021-06-26 12:53:46 【问题描述】:

我正在尝试为查询编写 typeDef。

import gql from "@apollo/client";

const typeDefs = gql`
    
    type Query
        rockets:[Rocket]!
        rocket(id:ID):Rocket!
    
    type Rocket 
        id:ID!
        name:String!
        mass:RocketMass
    
    type MassInt
        kg:Int
        
    type MassFloat
        kg:Float
    
    
    union Mass = MassInt|MassFloat

    type RocketMass 
        kg: Mass
        lb: Mass
    

`
export typeDefs

当我编写“GET_ROCKET”查询时,我的 IDE 中出现错误。

import gql from "@apollo/client";

const GET_ROCKETS = gql`
    query GetRockets 
        rockets
            id,
            name
        
    
`
const GET_ROCKET = gql`
    query GetRocket($id:ID!)
        rocket(id: $id)
        mass 
            kg,
            lb
        
        name
    
    
`
export GET_ROCKETS, GET_ROCKET

谁能解释我如何使用我的 typedef 中描述的属性“kg”和“lb”以及为什么我不能这样写联合? union Mass2 = Int|Float

【问题讨论】:

【参考方案1】:

MassInt.kgMassFloat.kg字段需要不同的名字,否则会抛出冲突错误。

见union types官方文档。

正确的typeDefsGET_ROCKET GraphQL 查询应该是这样的:

import express from 'express';
import  ApolloServer, gql  from 'apollo-server-express';
import faker from 'faker';
const app = express();

const typeDefs = gql`
  type Query 
    rockets: [Rocket]!
    rocket(id: ID): Rocket!
  
  type Rocket 
    id: ID!
    name: String!
    mass: RocketMass
  
  type MassInt 
    int: Int
  
  type MassFloat 
    float: Float
  

  union Mass = MassInt | MassFloat

  type RocketMass 
    kg: Mass
    lb: Mass
  
`;

const resolvers = 
  Query: 
    rocket: (_,  id ) => 
      return 
        id: 1,
        name: faker.lorem.word(),
        mass: 
          kg:  int: 100 ,
          lb:  float: 10.1 ,
        ,
      ;
    ,
  ,
  Mass: 
    __resolveType: (obj) => 
      if (isInt(obj.int)) 
        return 'MassInt';
      
      if (isFloat(obj.float)) 
        return 'MassFloat';
      
      return null;
    ,
  ,
;

function isInt(n) 
  return Number(n) === n && n % 1 === 0;


function isFloat(n) 
  return Number(n) === n && n % 1 !== 0;

const server = new ApolloServer( typeDefs, resolvers );
const port = 4000;
server.applyMiddleware( app, path: '/graphql' );
app.listen(port, () => console.log(`Apollo server started at http://localhost:$port`));
query GetRocket($id: ID)
  rocket(id: $id)
    id
    name
    mass 
      kg 
        ... on MassInt 
          int
        
        ... on MassFloat 
          float
        
      
      lb 
        ... on MassInt 
          int
        
        ... on MassFloat 
          float
        
      
    
  

查询结果:


  "data": 
    "rocket": 
      "id": "1",
      "name": "modi",
      "mass": 
        "kg": 
          "int": 100
        ,
        "lb": 
          "float": 10.1
        
      
    
  

【讨论】:

以上是关于如何描述嵌套对象的类型?如何描述联合类型?的主要内容,如果未能解决你的问题,请参考以下文章

从具有不同键的嵌套对象的值创建联合

如何将联合类型指定为对象键 Typescript

基于嵌套对象内属性的打字稿联合

无法让嵌套类型保护与打字稿中的联合类型一起使用

如何定义“类型析取”(联合类型)?

如何将元组类型转换为联合?