在 gatsby 中将 typescript 标记的联合添加到 graphql 查询的结果
Posted
技术标签:
【中文标题】在 gatsby 中将 typescript 标记的联合添加到 graphql 查询的结果【英文标题】:Adding typescript tagged unions to result from graphql query in gatsby 【发布时间】:2020-10-10 16:52:25 【问题描述】:我使用Typescript tagged unions 来检查函数参数使用的接口。这里有两个接口,每个接口都可以传入下面的func函数中
export interface IPubArticle
kind: "IPubArticle"
node:
fields:
slug: string
frontmatter:
title: string
category: string
author: string
issue: string
date: string
givenRank: number
export interface IArticleSquare
kind: "IArticleSquare"
node:
fields:
slug: string
frontmatter:
title: string
subTitle: string
category: string
author: string
featuredImage:
childImageSharp: IFluidObject
date: string
givenRank: number
const func = (data: data: IArticleSquare | IPubArticle) =>
switch (data.kind)
case "IArticleSquare":
...
case "IPubArticle":
...
我现在遇到了一个问题,因为显然我的 graphql 调用与接口不匹配,因为缺少变量类型
Argument of type ' node: fields: slug: string; ; frontmatter: title: string; subTitle: string; date: string; description: string; category: string; author: string; givenRank: number; featuredImage: childImageSharp: GatsbyImageProps; ; ; ; []' is not assignable to parameter of type 'IArticleSquare[]'.
Property 'kind' is missing in type ' node: fields: slug: string; ; frontmatter: title: string; subTitle: string; date: string; description: string; category: string; author: string; givenRank: number; featuredImage: childImageSharp: GatsbyImageProps; ; ; ; ' but required in type 'IArticleSquare'.ts(2345)
article.interface.ts(21, 3): 'kind' is declared here.
这是我的 graphql 查询
export const pageQuery = graphql`
query($path: string!)
allMarkdownRemark(
sort: order: DESC, fields: [frontmatter___date]
)
edges
node
fields
slug
frontmatter
title
subTitle
date(formatstring: "MMMM DD, YYYY")
category
featuredImage
childImageSharp
fluid(maxWidth: 400)
...GatsbyImageSharpFluid
我该如何解决这个问题?我真的不知道该怎么办
【问题讨论】:
API/服务器响应根本不包含kind
字段/属性,因此与您的定义不匹配...您应该使用基于服务器 defs/specs/typings 的类型...您可以通过featuredImage
识别这些类型
typescriptlang.org/docs/handbook/…
【参考方案1】:
假设IArticleSquareNode
在frontmatter
中总是有一个subtitle
而IArticleNode
没有,你可以写一个User-Defined Type Guard(isSquareNode
)来帮助你识别节点类型。
interface IFrontmatter
title: string
category: string
author: string
issue: string
date: string
givenRank: number
interface IFrontmatterSquare extends IFrontmatter
subTitle: string
interface IFields
slug: string
interface IArticleNode
fields: IFields
frontmatter: IFrontmatter
interface IArticleSquareNode
fields: IFields
frontmatter: IFrontmatterSquare
function isSquareNode(
node: IArticleSquareNode | IArticleNode,
): node is IArticleSquareNode
return (node as IArticleSquareNode).frontmatter.subTitle !== undefined
const func = (node: IArticleSquareNode | IArticleNode) =>
if (isSquareNode(node))
return 'is of type IArticleSquareNode'
else
return 'is of type IArticleNode'
const testArticleNode =
fields:
slug: '/myslug/',
,
frontmatter:
title: 'title',
category: 'category',
author: 'author',
issue: 'issue',
date: 'date',
givenRank: 1,
,
const testArticleSquareNode =
fields:
slug: '/myslug/',
,
frontmatter:
title: 'title',
subTitle: 'subTitle',
category: 'category',
author: 'author',
issue: 'issue',
date: 'date',
givenRank: 1,
,
console.log(func(testArticleNode)) // is of type IArticleNode
console.log(func(testArticleSquareNode)) // is of type IArticleSquareNode
【讨论】:
所以前端是从 Markdown 中提取的。我注意到当降价文件中没有列出 subTitle 属性时,subTittle 属性会用空字符串""
实例化。这算不算总是有子标题?
而且它必须使用类型保护?你不能使用标记工会?
如果您可以控制数据源,我想您可以使用标记联合。但鉴于您的问题,您似乎没有这样做。以上是关于在 gatsby 中将 typescript 标记的联合添加到 graphql 查询的结果的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Gatsby 中将 markdown frontmatter 显示为 HTML
使用 gatsby-plugin-categories / gatsby-plugin-tags 标记云和类别列表
在 Gatsby 应用程序中检测到多个全局站点标记 (gtag.js) 安装
Gatsby - WebpackError: Invariant Violation error with apolloClient