类型
# 核心概念
# Schema
用于定义数据模型的结构、字段的类型、模型间的关系,可以说是属于GraphQL
的核心。它其实就跟Typescript
很像,你在用的过程中就会发现,几乎只要你熟悉ts
,使用Schema
进行类型定义的时候会如鱼得水。
类型系统最终的目的主要是用来定义对象属性的形状,比如某个类型明确表示了对象中这个字段必须是Int
类型那么在返回数据时该字段你就就必须返回整型。
# 标量类型
这个可以类比于我们typescript
的原始类型。
Int
:有符号 32 位整数。Float
:有符号双精度浮点值。String
:UTF‐8 字符序列。Boolean
:true
或者false
。ID
:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
大部分的GraphQL
服务实现中,都有自定义标量类型的方式。例如,我们可以定义一个 Date
类型:
scalar Date
然后就取决于我们的实现中如何定义将其序列化、反序列化和验证。例如,你可以指定 Date
类型应该总是被序列化成整型时间戳,而客户端应该知道去要求任何 date
字段都是这个格式。
# 对象类型和字段
在使用GraphQL
来构建系统的过程中,最基本的组件就是对象类型,因为GraphQL
架构本质上就是在获取某个对象上的字段。
type ObjectOne {
name: String
age: Int
}
2
3
4
这就是一个最基本的对象类型,它描述了这个对象中各个字段的具体类型是什么,对象中当然也可以嵌套对象,正如我们使用Javascript
对象一样。
# 枚举类型
这个其实跟ts
中的使用方式差不多,也称作枚举(enum),枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内,它同样被序列化为String。这让你能够:
- 验证这个类型的任何参数是可选值的的某一个
- 与类型系统沟通,一个字段总是一个有限值集合的其中一个值。
定义方式如下:
enum Episode {
ONE
TWO
Three
}
2
3
4
5
也就是说,我们给某个属性定义成了Episode
,那么他的返回值一定是枚举类型中定义的三个值之一。
# 联合类型
联合类型相当于一组类型的集合。
type Cat{
wang: String!
}
type Fish{
miao: String!
}
union Animal = Cat | Fish
2
3
4
5
6
7
# 接口
如果有接触过ts
,那么这些概念可能对于你来说小菜一碟。方便查询时返回统一类型,接口是抽象的数据类型,因此只有接口的实现才有意义。
interface Animal {
name: String
}
type Dog implements Animal {
name: String
age: Int
}
2
3
4
5
6
7
8
上面代码表示如果你的类型被定义成Dog
,那么你返回的数据中就可能包含这name
、age
这两个属性(为什么用的是可能呢,因为这里没有添加必填标识符,后面会进行讲述)。
# 列表和非空
顾名思义,列表对应的就是用来描述一组数据而不是单个对象或单个字段,而非空类型相当于指定当前字段或者列表不得为空。
先看看他们分别长什么样(细心的同学会发现非空类型在前面代码中已经出现过了):
type Character {
name: String!
appearsIn: [String]!
test: [String!]
}
2
3
4
5
从代码中我们可以看到,部分字段的类型后面加上了**!**,这个符号就是表示非空类型,如果加上了这个符号,那么这个字段就被标记为非空,如果被加在列表后面那么久表示这个列表不得为空也就是至少要有一个值。
一般我们都会用[]
来表示这个字段是一个列表,然后在[]
中标识集合中每个数据的类型。在这里我们非空标识符加在不同地方又会有不同的含义,下面会进行一一讲述:
test: [String!]
这种方式表示就是列表内容可以为空,但是列表的每个项不得为空,这个代码中表示就是不得为空串。
test: [String]!
如果是符号在[]
的后面,那么就表示这个列表不得为空,也就是至少要有一个项或以上,但是可以包含空值成员。
# 输入类型
一般来说我们都会有一个需求,我们需要传递一整个对象并且对象中包含了多个属性作为查询参数来获取数据,那么输入类型就是用来定义这个对象的形状的,它的定义方式和对象类型几乎一样,只不过定义的关键字是input
。
input myInput {
name: String!
age: Int!
}
2
3
4