【发布时间】:2019-01-03 22:36:10
【问题描述】:
type GraphQLType =
| GraphQLInt
| GraphQLList<any>
| GraphQLNonNull<any>;
interface GraphQLInt {
int: number
}
interface GraphQLList<T> {
x: string
}
interface GraphQLNonNull<T> {
x: string
}
declare function isInt(type: GraphQLType): type is GraphQLInt;
declare function isList(type: GraphQLType): type is GraphQLList<any>;
declare function isNonNull(type: GraphQLType): type is GraphQLNonNull<any>;
function doIt(t: GraphQLType) {
if (isInt(t)) {
return t.int
}
if (isList(t)) {
// t: GraphQLList<any> | GraphQLNonNull<any>
return t.x
}
// t: never
if (isNonNull(t)) {
return t.x
}
}
上面的示例在 isNonNull() 块中导致错误,因为它确定 t 的类型为 never。在 isList() 块中,t 具有 GraphQLList 和 GraphQLNonNull 两种类型。这两种类型在结构上是相同的。这是here 和here 描述的同一个问题还是实际上是一个错误?
它应该起作用的原因是因为 isList() 是 GraphQLList 而不是 GraphQLNonNull 的类型保护,并且在运行时它会为 List 返回 true,为 NonNull 返回 false,但 typescript 似乎并不代表相同想法。
【问题讨论】:
-
TypeScript 对名义类型(不同名称的类型是不同的类型)的支持很少或不存在。如果你想让 TypeScript 知道两种类型是不同的,最好让它们在结构上有所不同。
GraphQLList和GraphQLNonNull之间没有结构上的区别(它们都没有使用它们的类型参数T)。如果你想让它工作,给它们一些不同的属性。 -
它们都没有使用它们的类型参数 T:这只是为了这个例子。我无法更改类型,它们来自 GraphQL.js
标签: typescript structural-typing