microsoft / microsoft/TypeScript

Confusing in narrowing and property access on type parameter with `never` base constraint

Abierto
#62,178 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Domain: check: Control Flow Help Wanted Possible Improvement
Lenguaje dominante
Go
Estrellas
111k
Forks
14.3k
Merge medio
2 d 4 h
PR fusionados (30 d)
132

Descripción

🔎 Search Terms

never in record unknown constraint base property access

🕗 Version & Regression Information
  • This is the behavior in every version I tried
⏯ Playground Link

https://www.typescriptlang.org/play/?ts=6.0.0-dev.20250802#code/CYUwxgNghgTiAEkoGdnwFoHtgBUCeADiADw4B88A3gFDzwD6mArgC4GsBc8OA3NQL7VqoJHETRUGbAHkARgCtwLYgGUAFlCIAaeNNbsWFEAA8WIAHbA0WXIRJ62rCjTr1kGol3WaQfQdRY7eABLcwAzEBh8IlJ4EzNLa2xokihzPDIKAF5uAG0AIkZ9VnyAXT5qULMYMKgwBBxMTAgVIjBgsODIqlp4cygAWxAuZBYYUIBzPjpQZDBxghZgzHMRscnp+BgmVfgACgJYQeQucxAAN0iASngsigAFGEwB4OQSUfHzCbI-IUCibhNCD3I5DarIWLxCxWQHNVrgDpdGDZeAgmCDEDg0gFbbmMpkXIABnKQhMBEwMBY8H+CAAghMLCxGs0ACIgWpMCAsFRgNQgAZQW5SYByRRgZRpPA6SU-UnGcmUkLmaq1erwemM5kQABCKBIvRUcVM0LQGuVWrZHK5PL5AqFZqZQMtUE53N5-KgWmozl6-SGa0+U16s3mwUWy12Hw2vVCBhtHq8vwCQQdWoAwlAIBBZHUANbEA1GhIw1NO9ku63uu05Uus8uu+MCr0ovawCYnJURKJ2VRkG53VFPF5vYgyipkilUqqRVV0hnmoEFuiGqGJdXzx11q1u22Cmsbi31yu75tFk3rzVA3UjlQ+ui4ri1iAZrM5sD529JmkXhd1uYLJYVlUM81yfZ0GyrKAURcPoMQDaMZhAf8w0AyN1i+TY5l3RNegfH9N2fTNszzXs-AqERoDEMIdnFCN4CgA9F0LVcS0YrcKx3D17TYiBwOPD1mz2ShYKGHQQwAiMdCwgSth2eB+EfHi2WQ8MgNvK5FMvZpSLlBUqWo8xaJWej+ggPBkFeLUl24ECYS1eF2k6SIvWXWykhFBQlFHdIdC1NEMSxcgyEElguBwKTIK8G4YLAFZRioESQDEpDQ1U8x5KFFhNjgFgmBgdKGK0iAhN6Og-SS0r4HElDJMq6Sm0qvCUDwQz9kOdEBmQfs7zoXqOn2fJySqfIlXgdrjngAAySbqTsTAwjG0FkAAOiG5VbiyHJ8ijL58miyresWjq0ByGDDsO5bLvGzqXPOuh+E2Q7BDunK8oKgB3KBgipFhltxA4lquR75Nu-ggYEIA

💻 Code
declare class ZodType<T> {
  _output: T;
}

declare class ZodObject<Shape, Output> extends ZodType<Output> {
  _shape: Shape;
}

type inferType<T extends ZodType<any>> = T["_output"];

interface ToolSpecifier {
  name: string;
  description: string;
  run: (params: never) => Promise<string>;
}

type ToolParameters<T extends ToolSpecifier> = Parameters<T["run"]>[0];

export type AgentToolDefaultSchema = ZodObject<any, any>;

export interface AgentToolBase<
  S extends AgentToolDefaultSchema = AgentToolDefaultSchema,
> {
  name: string;
  description: string;
  inputSchema: S;
}

type AgentToolCallback<
  S extends AgentToolDefaultSchema = AgentToolDefaultSchema,
> = (args: inferType<S>) => Promise<any>;

export interface AgentTool<
  S extends AgentToolDefaultSchema = AgentToolDefaultSchema,
> extends AgentToolBase<S> {
  run: AgentToolCallback<S>;
}

type AgentToolDescription<S extends AgentToolDefaultSchema> = {
  name: string;
  description: string;
  schema: S;
  run: AgentToolCallback<S>;
};

declare function agentTool<
  S extends AgentToolDefaultSchema = AgentToolDefaultSchema,
>({ name, description, schema, run }: AgentToolDescription<S>): AgentTool<S>;

export function analysisTool<
  T extends ToolSpecifier,
  S extends ZodObject<any, ToolParameters<T>>,
>(t: T, schema: S) {
  const { name, description } = t;
  return agentTool({
    name,
    description,
    schema,
    run: async (params) => {
      if ("point" in params && typeof params.point === "string") {
        params = {
          ...params,
        };
      }
      return await t.run(params);
    },
  });
}
🙁 Actual behavior
Property 'point' does not exist on type 'inferType<S> & Record<"point", unknown>'.(2339)
🙂 Expected behavior

This should be allowed or a better error should be reported

Additional information about the issue

This stems from inconsistent treatment of never:

declare const test: never;

if ("foo" in test) { // ok
}

test.foo; // error
test["foo"]; // ok
const { foo } = test; // ok

but given this whole thing happens at generic level it's not even apparent to the user they deal with a type parameter that has a never base constraint and that this might be the reason behind this confusing error

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza ejecutando la reproducción enlazada de TypeScript Playground y compara los diagnósticos de narrowing genérico y acceso a propiedades con los ejemplos independientes de never del issue. Sigue el comportamiento del checker para la rama "point" in params; se considera terminado cuando el comportamiento reportado sea consistente o el diagnóstico explique claramente la restricción de tipos subyacente.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
compilers
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.