Subscribe on changes!

defineComponent generic type error

avatar
Nov 5th 2021

Version

3.2.21

Reproduction link

github.com

Steps to reproduce

The type of the parameter props of the setup function and the generic type of DefineComponent<Props> should not be the same.

// overload 1: direct setup function
// (uses user defined props interface)
export function defineComponent<Props, RawBindings = object>(
  setup: (
    props: Readonly<Props>,
    ctx: SetupContext
  ) => RawBindings | RenderFunction
): DefineComponent<Props, RawBindings>

What is expected?

interface TestProps {
  name: string;
  age?: number;
}

export const Test = defineComponent<TestProps>(function Test(props) {
  return () => {
    return <div>{props.name}</div>;
  };
});
<Test />

The volar should prompt whether the prop name is required.

What is actually happening?

The volar don't prompt.


Would it be better?

type NonUndefinedable<T> = T extends undefined ? never : T;

export type DefinePropsToOptions<T> = {
  [K in keyof T]-?: Record<string, never> extends Pick<T, K>
    ? { type: PropType<NonUndefinedable<T[K]>> }
    : { type: PropType<T[K]>; required: true };
};

export function defineComponent<Props, RawBindings = object>(
  setup: (
    props: Readonly<Props>,
    ctx: SetupContext
  ) => RawBindings | RenderFunction
): DefineComponent<DefinePropsToOptions<Props>, RawBindings>

avatar
Nov 7th 2021

Declare a component like this, props are props that default to the browser’s native tags. Props cannot get name and age...😟 It seems to be inconsistent with the expected behavior, maybe I misunderstood it?

avatar
Nov 8th 2021

Declare a component like this, props are props that default to the browser’s native tags. Props cannot get name and age...😟 It seems to be inconsistent with the expected behavior, maybe I misunderstood it?

I think you should define props.

interface TestProps {
  name: string;
  age?: number;
}

export const Test = defineComponent<TestProps>(function Test(props) {
  return () => {
    return <div>{props.name}</div>;
  };
});

Test.props = ['name', 'age']
avatar
Nov 8th 2021

Declare a component like this, props are props that default to the browser’s native tags. Props cannot get name and age...😟 It seems to be inconsistent with the expected behavior, maybe I misunderstood it?

I think you should define props.

interface TestProps {
  name: string;
  age?: number;
}

export const Test = defineComponent<TestProps>(function Test(props) {
  return () => {
    return <div>{props.name}</div>;
  };
});

Test.props = ['name', 'age']

get!

avatar
Oct 10th 2022

像这样声明一个组件,props 是默认为浏览器原生标签的 props。道具无法获取名称和年龄...😟这似乎与预期的行为不一致,也许我误解了?

我认为你应该定义道具。

interface TestProps {
  name: string;
  age?: number;
}

export const Test = defineComponent<TestProps>(function Test(props) {
  return () => {
    return <div>{props.name}</div>;
  };
});

Test.props = ['name', 'age']

But,why? we should have a better way or api

avatar
Mar 2nd 2023

像这样声明一个组件,props 是默认为浏览器原生标签的 props。道具无法获取名称和年龄...😟这似乎与预期的行为不一致,也许我误解了?

我认为你应该定义道具。

interface TestProps {
  name: string;
  age?: number;
}

export const Test = defineComponent<TestProps>(function Test(props) {
  return () => {
    return <div>{props.name}</div>;
  };
});

Test.props = ['name', 'age']

But,why? we should have a better way or api

因为TS是不参与运行时的。在运行时会丢失所有类型的定义,就无法知道定义了哪些props。

@yinxulai