feat(traverse): specific return type for virtual types' validators (#13578)

* feat(traverse): specific return type for virtual types' validators

update generator script to use virtualType.types[0] as it's type

fix #13576

* fix: remove unused ts-expect-error

so glad that it works

* feat: use VirtualTypeAliases to generate validators for virtual types

* fix: return boolean when it doesn't have any alias

* fix: use type only import and simplify condition
This commit is contained in:
王清雨 2021-07-27 22:02:09 +08:00 committed by GitHub
parent 790c5180d4
commit e0dc925bbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 15 deletions

View File

@ -9,6 +9,7 @@ export default function generateValidators() {
*/
import * as t from "@babel/types";
import NodePath from "../index";
import type { VirtualTypeAliases } from "./virtual-types";
export interface NodePathValidators {
`;
@ -18,10 +19,18 @@ export interface NodePathValidators {
}
for (const type of Object.keys(virtualTypes)) {
const { types } = virtualTypes[type];
if (type[0] === "_") continue;
if (definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]) {
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
} else if (types /* in VirtualTypeAliases */) {
output += `is${type}(opts?: object): this is NodePath<VirtualTypeAliases["${type}"]>;`;
} else {
// if it don't have types, then VirtualTypeAliases[type] is t.Node
// which TS marked as always true
// eg. if (path.isBlockScope()) return;
// path resolved to `never` here
// so we have to return boolean instead of this is NodePath<t.Node> here
output += `is${type}(opts?: object): boolean;`;
}
}

View File

@ -153,7 +153,6 @@ function _evaluate(path: NodePath, state) {
}
if (path.isReferencedIdentifier()) {
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
const binding = path.scope.getBinding(path.node.name);
if (binding && binding.constantViolations.length > 0) {
@ -167,13 +166,10 @@ function _evaluate(path: NodePath, state) {
if (binding?.hasValue) {
return binding.value;
} else {
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
if (path.node.name === "undefined") {
return binding ? deopt(binding.path, state) : undefined;
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
} else if (path.node.name === "Infinity") {
return binding ? deopt(binding.path, state) : Infinity;
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
} else if (path.node.name === "NaN") {
return binding ? deopt(binding.path, state) : NaN;
}

View File

@ -4,6 +4,7 @@
*/
import * as t from "@babel/types";
import NodePath from "../index";
import type { VirtualTypeAliases } from "./virtual-types";
export interface NodePathValidators {
isAnyTypeAnnotation(opts?: object): this is NodePath<t.AnyTypeAnnotation>;
@ -416,22 +417,38 @@ export interface NodePathValidators {
isWhileStatement(opts?: object): this is NodePath<t.WhileStatement>;
isWithStatement(opts?: object): this is NodePath<t.WithStatement>;
isYieldExpression(opts?: object): this is NodePath<t.YieldExpression>;
isReferencedIdentifier(opts?: object): boolean;
isReferencedMemberExpression(opts?: object): boolean;
isBindingIdentifier(opts?: object): boolean;
isReferencedIdentifier(
opts?: object,
): this is NodePath<VirtualTypeAliases["ReferencedIdentifier"]>;
isReferencedMemberExpression(
opts?: object,
): this is NodePath<VirtualTypeAliases["ReferencedMemberExpression"]>;
isBindingIdentifier(
opts?: object,
): this is NodePath<VirtualTypeAliases["BindingIdentifier"]>;
isStatement(opts?: object): this is NodePath<t.Statement>;
isExpression(opts?: object): this is NodePath<t.Expression>;
isScope(opts?: object): boolean;
isScope(opts?: object): this is NodePath<VirtualTypeAliases["Scope"]>;
isReferenced(opts?: object): boolean;
isBlockScoped(opts?: object): boolean;
isVar(opts?: object): boolean;
isVar(opts?: object): this is NodePath<VirtualTypeAliases["Var"]>;
isUser(opts?: object): boolean;
isGenerated(opts?: object): boolean;
isPure(opts?: object): boolean;
isFlow(opts?: object): this is NodePath<t.Flow>;
isRestProperty(opts?: object): boolean;
isSpreadProperty(opts?: object): boolean;
isExistentialTypeParam(opts?: object): boolean;
isNumericLiteralTypeAnnotation(opts?: object): boolean;
isForAwaitStatement(opts?: object): boolean;
isRestProperty(
opts?: object,
): this is NodePath<VirtualTypeAliases["RestProperty"]>;
isSpreadProperty(
opts?: object,
): this is NodePath<VirtualTypeAliases["SpreadProperty"]>;
isExistentialTypeParam(
opts?: object,
): this is NodePath<VirtualTypeAliases["ExistentialTypeParam"]>;
isNumericLiteralTypeAnnotation(
opts?: object,
): this is NodePath<VirtualTypeAliases["NumericLiteralTypeAnnotation"]>;
isForAwaitStatement(
opts?: object,
): this is NodePath<VirtualTypeAliases["ForAwaitStatement"]>;
}

View File

@ -480,7 +480,6 @@ export function _resolve(
// otherwise it's a request for a pattern and that's a bit more tricky
}
} else if (this.isReferencedIdentifier()) {
// @ts-expect-error todo(flow->ts): think about options to improve type refinements
const binding = this.scope.getBinding(this.node.name);
if (!binding) return;