Skip to content
Go back

getConditionalFlowTypeOfType浅析typescript中的变体

Published:

getConditionalFlowTypeOfType

function getConditionalFlowTypeOfType(type: Type, node: Node) {
        let constraints: Type[] | undefined;
        let covariant = true;
        while (node && !isStatement(node) && node.kind !== SyntaxKind.JSDoc) {
            const parent = node.parent;
            // only consider variance flipped by parameter locations - `keyof` types would usually be considered variance inverting, but
            // often get used in indexed accesses where they behave sortof invariantly, but our checking is lax
            if (parent.kind === SyntaxKind.Parameter) {
                covariant = !covariant;
            }
            // Always substitute on type parameters, regardless of variance, since even
            // in contravariant positions, they may rely on substituted constraints to be valid
            if ((covariant || type.flags & TypeFlags.TypeVariable) && parent.kind === SyntaxKind.ConditionalType && node === (parent as ConditionalTypeNode).trueType) {
                const constraint = getImpliedConstraint(type, (parent as ConditionalTypeNode).checkType, (parent as ConditionalTypeNode).extendsType);
                if (constraint) {
                    constraints = append(constraints, constraint);
                }
            }
            // Given a homomorphic mapped type { [K in keyof T]: XXX }, where T is constrained to an array or tuple type, in the
            // template type XXX, K has an added constraint of number | `${number}`.
            else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && !(parent as MappedTypeNode).nameType && node === (parent as MappedTypeNode).type) {
                const mappedType = getTypeFromTypeNode(parent as TypeNode) as MappedType;
                if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) {
                    const typeParameter = getHomomorphicTypeVariable(mappedType);
                    if (typeParameter) {
                        const constraint = getConstraintOfTypeParameter(typeParameter);
                        if (constraint && everyType(constraint, isArrayOrTupleType)) {
                            constraints = append(constraints, getUnionType([numberType, numericStringType]));
                        }
                    }
                }
            }
            node = parent;
        }
        return constraints ? getSubstitutionType(type, getIntersectionType(constraints)) : type;
    }

getConditionalFlowTypeOfType 函数分析

getConditionalFlowTypeOfType 函数的目的是在 TypeScript 的抽象语法树(AST)中,根据给定的 type(类型)和 node(节点)上下文,确定该类型的有效流动类型。它通过向上遍历 AST,检查节点的父节点,追踪变体(协变或逆变)、收集约束,并应用必要的类型替换来实现这一点。该函数在处理条件类型、映射类型和类型参数时尤为重要。

函数目的与核心机制

变体追踪:参数位置与类型安全

条件类型中的类型参数替换

同态映射类型的特殊处理

最终类型替换


Suggest Changes

Next Post
typescript中的interface&type