<commit_before>import Vue, { VNode } from "vue";
import * as tsx from "vue-tsx-support";

function standardComponent() {
  const MyComponent = tsx.component(
    {
      props: {
        foo: String,
        bar: Number,
        baz: String
      },
      render(): VNode {
        return <span>{this.foo}</span>;
      }
    },
    /* requiredPropNames */ ["foo", "bar"]
  );

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // baz is optional
  <MyComponent foo="foo" bar={0} />;
  // other known attributes
  <MyComponent foo="foo" bar={0} key="xxx" id="xxx" />;

  /* NG */
  <MyComponent />; //// TS2322 | TS2326 | TS2769
  <MyComponent foo="foo" />; //// TS2322 | TS2326 | TS2769: Property 'bar' is missing
  <MyComponent foo={0} bar={1} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="foo" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="foo" bar={0} baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="foo" bar={0} unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function functionalComponent() {
  const MyComponent = tsx.component(
    {
      functional: true,
      props: {
        foo: String,
        bar: Number,
        baz: String
      },
      render(_h, ctx): VNode {
        return <span>{ctx.props.foo}</span>;
      }
    },
    ["foo", "bar"]
  );
  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // baz is optional
  <MyComponent foo="foo" bar={0} />;
  // other known attributes
  <MyComponent foo="foo" bar={0} key="xxx" id="xxx" />;

  /* NG */
  <MyComponent />; //// TS2322 | TS2326 | TS2769
  <MyComponent foo="foo" />; //// TS2322 | TS2326 | TS2769: Property 'bar' is missing
  <MyComponent foo={0} bar={1} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="foo" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="foo" bar={0} baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="foo" bar={0} unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function withoutRequiredPropNames() {
  const MyComponent = tsx.componentFactory.create({
    props: {
      foo: String,
      bar: Number,
      baz: String
    },
    render(): VNode {
      return <span>{this.foo}</span>;
    }
  });

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // foo, bar, baz are all optional
  <MyComponent />;
  // other known attributes
  <MyComponent key="xxx" id="xxx" />;

  /* NG */
  <MyComponent foo={0} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function inferRequiredPropNames() {
  const MyComponent = tsx.componentFactory.create({
    props: {
      foo: { type: String, required: true as true },
      bar: { type: Number, required: false },
      baz: String
    },
    render(): VNode {
      return <span>{this.foo}</span>;
    }
  });

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // foo is required, bar and baz are optional
  <MyComponent foo="foo" />;
  <MyComponent />; //// TS2322 | TS2326 | TS2769: Property 'foo' is missing
  // other known attributes
  <MyComponent foo="foo" key="xxx" id="xxx" />;

  /* NG */
  <MyComponent foo={0} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="a" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="a" baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="a" unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function withWrongRequiredPropNames() {
  const MyComponent = tsx.component({ props: { foo: String } }, ["foo", "unknown"]); //// TS2345 | TS2769
}

function componentFactoryOf() {
  const factory = tsx.componentFactoryOf<
    { onChange: number | string; onOk(target: any, id: string): void },
    { content: string }
  >();
  const MyComponent = factory.create({
    props: {
      foo: String,
      bar: Number
    },
    computed: {
      okNode(): VNode {
        return <div>{this.$scopedSlots.content("foo")}</div>;
      },
      ngNode(): VNode {
        return <div>{this.$scopedSlots.content(0)}</div>; //// TS2345: '0' is not assignable
      }
    },
    render(): VNode {
      return <div>{[this.okNode, this.ngNode]}</div>;
    }
  });

  /* checking type of scopedSlots */
  <MyComponent scopedSlots={{ content: p => p }} />;
  <MyComponent scopedSlots={{ content: (p: number) => p.toString() }} />; //// TS2322 | TS2326 | TS2769: 'string' is not assignable
  <MyComponent scopedSlots={{}} />; //// TS2322 | TS2326 | TS2741 | TS2769: Property 'content' is missing

  /* checking type of custom event handler */
  <MyComponent onChange={_v => {}} />;
  <MyComponent onChange={(_v: string | number) => {}} />;
  <MyComponent onChange={(_v: number) => {}} />; //// TS2322 | TS2326 | TS2769: '(_v: number) => void' is not assignable
  <MyComponent onChange={(_v: string) => {}} />; //// TS2322 | TS2326 | TS2769: '(_v: string) => void' is not assignable
  <MyComponent
    onOk={(_, id) => {
      console.log(id);
    }}
  />;
}

function optionalScopedSlot() {
  const factory = tsx.componentFactoryOf<{}, { required: string; optional?: number }>();<commit_msg>fix test which fails with TS4.0<commit_after>import Vue, { VNode } from "vue";
import * as tsx from "vue-tsx-support";

function standardComponent() {
  const MyComponent = tsx.component(
    {
      props: {
        foo: String,
        bar: Number,
        baz: String
      },
      render(): VNode {
        return <span>{this.foo}</span>;
      }
    },
    /* requiredPropNames */ ["foo", "bar"]
  );

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // baz is optional
  <MyComponent foo="foo" bar={0} />;
  // other known attributes
  <MyComponent foo="foo" bar={0} key="xxx" id="xxx" />;

  /* NG */
  <MyComponent />; //// TS2322 | TS2326 | TS2769
  <MyComponent foo="foo" />; //// TS2322 | TS2326 | TS2769: Property 'bar' is missing
  <MyComponent foo={0} bar={1} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="foo" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="foo" bar={0} baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="foo" bar={0} unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function functionalComponent() {
  const MyComponent = tsx.component(
    {
      functional: true,
      props: {
        foo: String,
        bar: Number,
        baz: String
      },
      render(_h, ctx): VNode {
        return <span>{ctx.props.foo}</span>;
      }
    },
    ["foo", "bar"]
  );
  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // baz is optional
  <MyComponent foo="foo" bar={0} />;
  // other known attributes
  <MyComponent foo="foo" bar={0} key="xxx" id="xxx" />;

  /* NG */
  <MyComponent />; //// TS2322 | TS2326 | TS2769
  <MyComponent foo="foo" />; //// TS2322 | TS2326 | TS2769: Property 'bar' is missing
  <MyComponent foo={0} bar={1} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="foo" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="foo" bar={0} baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="foo" bar={0} unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function withoutRequiredPropNames() {
  const MyComponent = tsx.componentFactory.create({
    props: {
      foo: String,
      bar: Number,
      baz: String
    },
    render(): VNode {
      return <span>{this.foo}</span>;
    }
  });

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // foo, bar, baz are all optional
  <MyComponent />;
  // other known attributes
  <MyComponent key="xxx" id="xxx" />;

  /* NG */
  <MyComponent foo={0} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function inferRequiredPropNames() {
  const MyComponent = tsx.componentFactory.create({
    props: {
      foo: { type: String, required: true as true },
      bar: { type: Number, required: false },
      baz: String
    },
    render(): VNode {
      return <span>{this.foo}</span>;
    }
  });

  /* OK */
  <MyComponent foo="foo" bar={0} baz="baz" />;
  // foo is required, bar and baz are optional
  <MyComponent foo="foo" />;
  <MyComponent />; //// TS2322 | TS2326 | TS2769: Property 'foo' is missing
  // other known attributes
  <MyComponent foo="foo" key="xxx" id="xxx" />;

  /* NG */
  <MyComponent foo={0} />; //// TS2322 | TS2326 | TS2769: /'(0|number)' is not assignable/
  <MyComponent foo="a" bar="bar" />; //// TS2322 | TS2326 | TS2769: /'("bar"|string)' is not assignable/
  <MyComponent foo="a" baz={1} />; //// TS2322 | TS2326 | TS2769: /'(1|number)' is not assignable/
  <MyComponent foo="a" unknown="unknown" />; //// TS2322 | TS2339 | TS2769: Property 'unknown' does not exist
}

function withWrongRequiredPropNames() {
  const MyComponent = tsx.component({ props: { foo: String } }, ["foo", "unknown"]); //// TS2345 | TS2769
}

function componentFactoryOf() {
  const factory = tsx.componentFactoryOf<
    { onChange: number | string; onOk(target: any, id: string): void },
    { content: string }
  >();
  const MyComponent = factory.create({
    props: {
      foo: String,
      bar: Number
    },
    computed: {
      okNode(): VNode {
        return <div>{this.$scopedSlots.content("foo")}</div>;
      },
      ngNode(): VNode {
        return <div>{this.$scopedSlots.content(0)}</div>; //// TS2345: /'0|number' is not assignable/
      }
    },
    render(): VNode {
      return <div>{[this.okNode, this.ngNode]}</div>;
    }
  });

  /* checking type of scopedSlots */
  <MyComponent scopedSlots={{ content: p => p }} />;
  <MyComponent scopedSlots={{ content: (p: number) => p.toString() }} />; //// TS2322 | TS2326 | TS2769: 'string' is not assignable
  <MyComponent scopedSlots={{}} />; //// TS2322 | TS2326 | TS2741 | TS2769: Property 'content' is missing

  /* checking type of custom event handler */
  <MyComponent onChange={_v => {}} />;
  <MyComponent onChange={(_v: string | number) => {}} />;
  <MyComponent onChange={(_v: number) => {}} />; //// TS2322 | TS2326 | TS2769: '(_v: number) => void' is not assignable
  <MyComponent onChange={(_v: string) => {}} />; //// TS2322 | TS2326 | TS2769: '(_v: string) => void' is not assignable
  <MyComponent
    onOk={(_, id) => {
      console.log(id);
    }}
  />;
}

function optionalScopedSlot() {
  const factory = tsx.componentFactoryOf<{}, { required: string; optional?: number }>();
{'fraction_non_alphanumeric': 0.1967867998263135, 'fraction_numerical': 0.06061658706035606, 'mean_word_length': 2.8839797639123104, 'pattern_counts': {'":': 0, '<': 117, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1194779', 'n_tokens_mistral': 4554, 'n_tokens_neox': 4044, 'n_words': 1013}