Skip to content

"Type of property 'value' circularly references itself in mapped type" error or type resolving to any #315

@Athari

Description

@Athari

Describe the bug
When I try pattern-matching component values of @csstools/css-tokenizer, I either get an error, or the type of a in a => a is resolved to any. Also type analysis within VSCode becomes extremely slow. That's within VSCode; I didn't get to actually running any of this code.

If I remove value: Array<ComponentValue> in ContainerNodeBaseClass, the error goes away. Same with removing SimpleBlockNode type. If I remove TokenNode type, the error goes away, but a is resolved to any.

TypeScript playground with a minimal reproduction case

Example: Playground

import { match, P } from 'ts-pattern';

export declare enum TokenType {
  Comment = "comment",
  Function = "function-token",
  Ident = "ident-token",
  Number = "number-token",
  Whitespace = "whitespace-token",
}

export declare interface Token<T extends TokenType, U> extends Array<T | string | number | U> {
  0: T;
  1: string;
  2: number;
  3: number;
  4: U;
}

export declare interface TokenComment extends Token<TokenType.Comment, undefined> {}

export declare interface TokenFunction extends Token<TokenType.Function, {  value: string;}> {}

export declare interface TokenIdent extends Token<TokenType.Ident, { value: string; }> {}

export declare interface TokenNumber extends Token<TokenType.Number, { value: number; }> {}

export declare interface TokenWhitespace extends Token<TokenType.Whitespace, undefined> {}

export declare interface TokenFunction extends Token<TokenType.Function, { value: string; }> { }

export declare type CSSToken = TokenComment | TokenFunction | TokenIdent | TokenNumber | TokenWhitespace;

export declare class CommentNode {
  type: ComponentValueType;
  value: CSSToken;
}

export declare type ComponentValue = FunctionNode | SimpleBlockNode | CommentNode | TokenNode;

export declare enum ComponentValueType {
  Function = "function",
  SimpleBlock = "simple-block",
  Whitespace = "whitespace",
  Comment = "comment",
  Token = "token"
}

export declare type ContainerNode = FunctionNode | SimpleBlockNode;

export declare abstract class ContainerNodeBaseClass {
  value: Array<ComponentValue>;
}

export declare class FunctionNode extends ContainerNodeBaseClass {
  type: ComponentValueType;
  name: TokenFunction;
  endToken: CSSToken;
}

export declare class SimpleBlockNode extends ContainerNodeBaseClass {
  type: ComponentValueType;
  startToken: CSSToken;
  endToken: CSSToken;
}

export declare class TokenNode {
  type: ComponentValueType;
  value: CSSToken;
}

export declare function isFunctionNode(x: unknown): x is FunctionNode;

declare const comps: ComponentValue[];

match(comps).with([P.select(P.when(isFunctionNode))], a => a);

Versions

  • TypeScript version: 5.7.3 (5.8.2 in playground)
  • ts-pattern version: 5.6.2
  • environment: Node 20.11.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions