rhys-vdw / ts-auto-guard

Generate type guard functions from TypeScript interfaces
MIT License
502 stars 55 forks source link

Recursive type guards created by overwriting existing _.guard.ts file only test typeof === "object" #80

Open aneilbaboo opened 4 years ago

aneilbaboo commented 4 years ago

I noticed that the typeguards for these recursive types don't perform a useful test:

index.ts:

// Recursion
/** @see {isRecursiveType} ts-auto-guard:type-guard */
export type RecursiveType = { children: RecursiveType[] };

// Mutual recursion
/** @see {isParentType} ts-auto-guard:type-guard */
export type ParentType = { type: 'parent', children: ChildType[] };

/** @see {isChildType} ts-auto-guard:type-guard */
export type ChildType = { type: 'child', parent: ParentType };

index.guard.ts:


export function isRecursiveType(obj: any, _argumentName?: string): obj is RecursiveType {
    return (
        typeof obj === "object"
    )
}

export function isParentType(obj: any, _argumentName?: string): obj is ParentType {
    return (
        typeof obj === "object"
    )
}

export function isChildType(obj: any, _argumentName?: string): obj is ChildType {
    return (
        typeof obj === "object"
    )
}
aneilbaboo commented 4 years ago

Aha - I just noticed that this happens when there's an existing index.guard.ts file. Deleting the guard file and re-running ts-auto-guard results in the correct code being generated:


export function isRecursiveType(obj: any, _argumentName?: string): obj is RecursiveType {
    return (
        typeof obj === "object" &&
        Array.isArray(obj.children) &&
        obj.children.every((e: any) =>
            isRecursiveType(e) as boolean
        )
    )
}

export function isParentType(obj: any, _argumentName?: string): obj is ParentType {
    return (
        typeof obj === "object" &&
        obj.type === "parent" &&
        Array.isArray(obj.children) &&
        obj.children.every((e: any) =>
            isChildType(e) as boolean
        )
    )
}

export function isChildType(obj: any, _argumentName?: string): obj is ChildType {
    return (
        typeof obj === "object" &&
        obj.type === "child" &&
        isParentType(obj.parent) as boolean
    )
}

EDIT: Updated the title to reflect this.

rhys-vdw commented 4 years ago

Woah, that's mystifying... I've just invited you to be a collaborator if you're interested as I am not actively working on this project.

aneilbaboo commented 4 years ago

@rhys-vdw, cool - can't promise I will have results, but if I have some time, I'll take a look.

rhys-vdw commented 4 years ago

All good, no expectation. Just gave the role in case you need to fix anything or I'm taking too long to merge something.

aneilbaboo commented 4 years ago

Thx