wonderful-panda / vue-tsx-support Goto Github PK
View Code? Open in Web Editor NEWTSX (JSX for TypeScript) support library for Vue
License: MIT License
TSX (JSX for TypeScript) support library for Vue
License: MIT License
I am not the best at Typescript, so this type may be off a little, but I noticed that when trying to make pure function components two things happened:
props
objectSo with this typing, it allows you to pass an interface or a type as a parameter for props, and it will strongly type them in the arguments and on the TSX element for you:
import { RenderContext } from 'vue'
type Maybe<T> = T | undefined | null
type TsxComponent<Props> = (
args: Partial<RenderContext<Props>> & {
[k in keyof Props]: Maybe<Props[k]>
}
) => VueTsxSupport.JSX.Element
interface LabelInputProps {
name: string
type: string
}
const LabeledInput: TsxComponent<LabelInputProps> = ({props}) => {
return (
<div>
<p>{props.name}</p>
<input type={props.type} />
</div>
)
}
A warning about this though:
This works through a hack, by copying the properties of the type you pass into TsxComponent<Props>
into the argument definitions at the TOP LEVEL. Because the TSX Element seems to autocomplete the parameters as all top-level arguments instead of just props
.
RenderContext<Props>
adds the types to the { props }
definitions, and then [k in keyof Props]: Maybe<T[Props]>
adds them to the top-level as well so that they appear as autocomplete options in the TSX Element.
This makes them incorrectly appear as argument values outside of props
when destructuring in the function parameters too.
If anyone knows how to make this type so that it shows up on the TSX element autocomplete but not in the top-level function params, please post ideas. I think this may not be possible since they have to share a single type definition.
Docs: https://vuejs.org/v2/guide/forms.html#Modifiers
How can we use something like this:
<input v-model.number="age" type="number">
I do this on almost all of my components:
<MyComponent
mode={this.mode}
on={{'update:mode': (val: string) => (this.mode = val)}}
/>
it could be greatly improved if the sync modifier syntax was available:
<MyComponent
mode.sync={this.mode}
/>
Is it possible to add this feature to vue-tsx-support?
I'm getting this error:
Property '$scopedSlots' in type 'Component<Props, EventsWithOn, ScopedSlotArgs>' is not assignable to the same property in base type 'object & Record<never, any> & Vue'.
Type 'ScopedSlots<ScopedSlotArgs>' is not assignable to type '{ [key: string]: ScopedSlot | undefined; }'.
Index signatures are incompatible.
Type '(props: any) => string | VNodeChildrenArrayContents' is not assignable to type 'ScopedSlot'.
Type 'string | VNodeChildrenArrayContents' is not assignable to type 'ScopedSlotChildren'.
Type 'VNodeChildrenArrayContents' is not assignable to type 'ScopedSlotChildren'.
Type 'VNodeChildrenArrayContents' is not assignable to type 'ScopedSlotArrayContents'.
Types of property 'pop' are incompatible.
Type '() => string | boolean | VNode | VNodeChildrenArrayContents | [ScopedSlot] | null | undefined' is not assignable to type '() => ScopedSlotChildren'.
Type 'string | boolean | VNode | VNodeChildrenArrayContents | [ScopedSlot] | null | undefined' is not assignable to type 'ScopedSlotChildren'.
Type 'null' is not assignable to type 'ScopedSlotChildren'.
11 | export declare class Component<Props, EventsWithOn = {}, ScopedSlotArgs = {}> extends Vue {
12 | _tsxattrs: TsxComponentAttrs<Props, EventsWithOn, ScopedSlotArgs>;
> 13 | $scopedSlots: ScopedSlots<ScopedSlotArgs>;
| ^
14 | }
15 | /**
16 | * Create component from component options (Compatible with Vue.extend)
Version: typescript 3.2.2
it also throws the same error with typescript 3.1.6
I recently tried to upgrade my project deps, upgrading vue to "2.5.21"
.
I'm using tsx.componentFactoryOf<IEvents>().create({})
and I have some Vue plugins that inject additional fields into my Vue components. How can I make Typescript aware of these additional fields? (similar to this.$router
)
const LazyComp = () => import('@/LazyComp');
and somewhere below in render function:
<LazyComp />
Runtime is ok, but Typescript is not:
JSX element type 'Promise<typeof import("path/to/LazyComp")>' is not a constructor function for JSX elements.
Type 'Promise<typeof import("path/to/LazyComp")>' is missing the following properties from type 'Element': isRootInsert, isComment
Hi, some interesting features came to TS 2.8
https://blogs.msdn.microsoft.com/typescript/2018/03/27/announcing-typescript-2-8/#jsx-pragma-comments
https://medium.com/@gigobyte/custom-type-errors-and-input-validation-in-typescript-2-8-bca4fa6b2940
https://medium.com/@martin_hotell/improved-redux-type-safety-with-typescript-2-8-2c11a8062575
for example, I used el-pagination
firstly, I created its types
import { Pagination } from "element-ui"
interface ElPaginationProps1 extends ElPaginationBaseProps {
total: number;
}
interface ElPaginationProps2 extends ElPaginationBaseProps {
pagerCount: number;
}
type ElPaginationProps = ElPaginationProps1 | ElPaginationProps2
interface ElPaginationEvents {
onSizeChange: number;
onCurrentChange: number;
onPrevClick: number;
onNextClick: number;
}
export const ElPagination = tsx.ofType<ElPaginationProps, ElPaginationEvents>().convert(Pagination)
then when I use it
<ElPagination
pageSize={1}
currentPage={1}
total={1}
onCurrentChange={ num => console.log("hi") }
></ElPagination>
Above code does not work as expected. in vue dev tools you can see the ElPagination instance's $listener only has one which so called "currentChange"
In fact, I want listen the "current-change" event
Maybe someone will say: why don't u use "on-current-change" instead. If so, we will lose the type check, ide would not know the variable num was number
I am running into a problem that I dont think is how it used to work, but not sure.
Given my component.
import Vue, { VNode } from 'vue';
import * as tsx from "vue-tsx-support";
import { Component, Prop, Watch } from 'vue-property-decorator';
export interface SiHomeSectionTags {
title: string;
}
@Component
export default class SiHomeSection extends tsx.Component<SiHomeSectionTags>{
@Prop()
title!: string;
render() {
return [
<header class="fxs-home-title" aria-label={this.title}>{this.title}</header>,
<div class="fxs-home-section">
{this.$slots.default}
</div>
];
}
}
i cant use title as an attribute, but have to use props= - is that intended?
Technically, Events are a relationship with Props:
interface SProps {
multiple: false
value: T
}
interface MProps {
multiple: true
value: T[]
}
interface SEvents {
onInput: (v: T) =>void
}
interface MEvents {
onInput: (v: T[]) =>void
}
type Props = SProps | MProps
type Events = SEvents | MEvents
class A extends tsx.Component<Props, Events> {
}
const S = <A multiple={false} value={1} onInput={/**/} />
const M = <A multiple={true} value={[1]} onInput={/**/} />
In that case, we could inference type of value from 'multiple' property, but seems no idea about onInput
event ((v: any) =>any
on ts@next), Even though it works, the type of that should be(v: T | T[]) =>void
, that is not the type we expected,
Could we provide a new API to create relationship events from props? Maybe that is helpful to that case
eg:
type SArgs = [SProps, SEvents]
type MArgs = [MProps, MProps]
class A extends tsx.Or<SArgs , MArgs> {
}
Creating a component constructor from a generic function that has any properties of those types will not compile in markup. It produces the following compiler error based on the provided example:
${projectDir}/render/app/components/test.tsx:54:36: No overload matches this call.
Overload 1 of 3, '(options?: ThisTypedComponentOptionsWithArrayProps<{ _tsxattrs: TsxComponentAttrs<{ options: T[]; } & { value?: V | undefined; }, {}, {}>; } & Vue & { innerValue: number | undefined; } & { onChange(value: number): void; } & { ...; } & { ...; }, object, object, object, never> | undefined): CombinedVueInstance<...>', gave the following error.
Type '{ label: string; value: number; }[]' is not assignable to type 'T[]'.
Type '{ label: string; value: number; }' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '{ label: string; value: number; }'.
Overload 2 of 3, '(options?: ThisTypedComponentOptionsWithRecordProps<{ _tsxattrs: TsxComponentAttrs<{ options: T[]; } & { value?: V | undefined; }, {}, {}>; } & Vue & { innerValue: number | undefined; } & { onChange(value: number): void; } & { ...; } & { ...; }, object, object, object, object> | undefined): CombinedVueInstance<...>', gave the following error.
Type '{ label: string; value: number; }[]' is not assignable to type 'T[]'.
Overload 3 of 3, '(options?: ComponentOptions<{ _tsxattrs: TsxComponentAttrs<{ options: T[]; } & { value?: V | undefined; }, {}, {}>; } & Vue & { innerValue: number | undefined; } & { onChange(value: number): void; } & { ...; } & { ...; }, ... 4 more ..., Record<...>> | undefined): CombinedVueInstance<...>', gave the following error.
Type '{ label: string; value: number; }[]' is not assignable to type 'T[]'. [TS2769]
Example:
import { PropOptions, PropType, VNode } from "vue";
import * as tsx from "vue-tsx-support";
const options = [
{ label: "Option One", value: 1 },
{ label: "Option Two", value: 2 },
{ label: "Option Three", value: 3 },
];
type Option = typeof options[number];
function select<T, V extends number|string>(predicate: (option: T) => [ string, V ]) {
return tsx.component({
name: "Select",
props: {
value: { default: undefined } as PropOptions<V>,
options: { type: Array as PropType<T[]>, required: true },
},
data: function () {
return {
innerValue: this.value as V|undefined,
};
},
computed: {
label(): string {
const value = this.options.find(option => predicate(option)[1] === this.innerValue);
return value ? predicate(value)[0] : "Required";
},
},
methods: {
onChange(value: V) {
this.innerValue = value;
this.$emit("change", value);
},
},
render(): VNode {
return (<select value={this.innerValue} onChange={value => this.onChange(value as any)}>{
this.options.map(option => (
<option value={predicate(option)[1]}>{predicate(option)[0]}</option>
))
}</select>);
},
});
}
// OptionSelect is typeof Select<Option, number>;
const OptionSelect = select((option: Option) => [ option.label, option.value ]);
// @vue/component
const test = tsx.component({
name: "test",
render(): VNode {
return (<div><OptionSelect options={options}/></div>);
},
});
type test = InstanceType<typeof test>;
export default test;
None of the DOM types exposed by /types/dom.d.ts
are using the Type Literals feature - and it would work great I think.
Example: this is the current declaration for the "type" attribute on the "input" interface:
type?: string;
A more accurate type definition would be:
type?: 'text' | 'button' | 'submit'; // other literals are omitted for brevity
this will allow intellisense to suggest possible values for type
.
same if true for other attributes
Hello,
I have an issue when trying to create a vue component using a generic factory function. The problem is that the generic type never gets "resolved" to an actual type. It always stays T instead of becoming something useful like SomeType.
To be honest I am not sure if this is a limitation in vue, vue-tsx-support or TypeScript itself. Maybe someone could help clarify the issue or see if this is an actual error?
Here is what I am trying to do:
// define a generic component factory function
function myComponentFactory<T>() {
return component( {
name: 'MyComponent',
render() {
return (
<ul>
{ this.options.map( ( el, i ) =>
<li key={i}>
<span>{el[ this.label ]}</span>
</li>,
) }
</ul>
);
},
props: {
// use the generic type as prop type for 'options' array
options: type( Array as () => T[] )
.required,
// use generic keyof T type for label
label: type( String as () => string as () => keyof T )
.required,
},
} );
}
Now my hope was that by calling the factory function with a specific type the prop types would assume this given type as well. Unfortunately this does not work:
// Define type for factory function
interface Option {
readonly foo: string;
readonly bar: number;
}
// call generic factory function and specify the type
const MyComponent = myComponentFactory<Option>();
component( {
name: 'Container',
render() {
return (
<MyComponent
// 'options' now should be typed as Option[]
// but it is still typed as T[]
// TypeScript throws error because 'Option' is not assignable to 'T'
options={this.myCompOptions}
// 'label' should be typed foo | bar
// but it is still typed as keyof T
// again, Typescript error
label={'foo'} />
);
},
computed: {
myCompOptions(): Option[] {
return [
{
foo: 'baz1',
bar: 1,
},
{
foo: 'baz2',
bar: 2,
},
{
foo: 'baz3',
bar: 3,
},
];
},
},
} );
Are generic prop types even possible? Any idea how this could be handled?
What is a way to include .tsx components dynamically by path / name?
Something like Async Components is needed.
For example including .vue
file work in this case:
const Widget = () => ({
component: import('./AboutUs/1.vue'),
// loading: LoadingComponent,
// error: ErrorComponent,
delay: 200,
timeout: 3000
})
export default Widget
But with .tsx
fdoesn't work with both ./AboutUs/2.tsx
or ./AboutUs/2
:
const Widget = () => ({
component: import('./AboutUs/2.tsx'),
// loading: LoadingComponent,
// error: ErrorComponent,
delay: 200,
timeout: 3000
})
export default Widget
The last one gives an error render function or template not defined in component: anonymous
I have a question about the htmlfor
attribute for <label>
:
vue-tsx-support/types/dom.d.ts
Line 209 in 36be27a
First of all, shouldn't this be camel case, like htmlFor
? Or doesn't this matter? https://reactjs.org/docs/dom-elements.html#htmlfor
In any case, using htmlfor
(or htmlFor
when I change the type definition) does not result in having <label for="...">
in the HTML but <label htmlfor="...">
. Does anyone know why this is happening? Maybe this is an issue with the vue jsx babel preset (https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx)?
In VDataTable of vuetify-tsx
based on vue-tsx-support
, how to show data in table body with slots? Any examples?
<VDataTable items={mockItems} headers={mockHeaders}>
<tr slot={"mockHeaders"} scopedSlots={{ props: (props)=> ... }} >
</tr>
</VDataTable>
How did the slots work?
Thanks!
Excuse me.
I want to create a component with dynamicn data, but i found the dynamic data can not be hint in the component.
for example:
// base component
import { Component, tsx } from "@/helper/support";
@Component
export default class DemoComponent extends tsx.Component<{}> {
// the data is dynamic, such as `from`
protected render() {
return <p>from values: {(this as any).from}</p>;
}
}
// a method to create the singleton component
function declareSingleComponent<ComponentProps>(component: any) {
const Component = Vue.extend(component);
return (params: ComponentProps | object = {}): Promise<Component> => {
if (instance) return instance;
return new Promise((resolve, reject) => {
instance = new Component({
el: document.createElement("div"),
data: Object.assign({ visible: true }, params),
methods: {
resolve,
reject,
close() {
this.visible = false;
resolve(this.$data);
}
}
});
document.body.appendChild(instance.$el);
});
};
}
// use
import DemoComponent from "./demo";
// DemoComponent's data interface
// i want to hint this in the base component
interface DemoComponentProps {
from?: string;
}
const demo = declareSingleComponent<DemoComponentProps>(DemoComponent);
@Component
export default class PageComponent extends tsx.Component<{}> {
protected showComponent() {
demo({ from: "i am showing while click" })
}
protected render() {
return <p onClick={this.showComponent}>click to show component</p>;
}
}
it can run without error, but in the base componen can not hint the data.
maybe u can provide some good ways to help me improve this.
thx~
// main.ts
import "vue-tsx-support/enable-check"
import "vue-tsx-support/options/allow-unknown-props";
const ToolbarTyped = tsx.ofType<{ tools: ITool[] }>().convert(Toolbar);
return (
<div>
<ToolbarTyped tools={this.tools} />
</div>);
Error:(34, 18) TS2322: Type '{ tools: ITool[]; }' is not assignable to type 'ComponentOptions<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar, DefaultData<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar>, DefaultMethods<{ _tsxattrs: TsxComponentAttrs<...>; } & Toolbar>, DefaultComputed, PropsDefinition<...>, Record<...>>'.
Property 'tools' does not exist on type 'ComponentOptions<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar, DefaultData<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar>, DefaultMethods<{ _tsxattrs: TsxComponentAttrs<...>; } & Toolbar>, DefaultComputed, PropsDefinition<...>, Record<...>>'.
Whole project use Element-ui, so i global registered some basic components, like this:
import { Row, Button, Select } from 'element-ui'
import 'element-ui/packages/theme-chalk/src/row.scss'
import 'element-ui/packages/theme-chalk/src/icon.scss'
import 'element-ui/packages/theme-chalk/src/button.scss'
import 'element-ui/packages/theme-chalk/src/select.scss'
Vue.use(Row)
Vue.use(Button)
Vue.use(Select)
use like this:
import { CreateElement } from 'vue'
import { Component, Vue } from 'vue-property-decorator'
import $style from './index.module.scss'
@Component
export default class extends Vue {
private render(h: CreateElement) {
return (
<ElRow class={$style.wrapper}>
<ElButton>this is a button</ElButton>
</ElRow>
)
}
}
runing correct, but IDE and console show error message: Cannot find name 'ElRow'
how can i use it in tsx not show error message?
I am writing a popup component using vue-tsx-support.
const popupWrapper = componentFactoryOf<PopupWrapperEvents>().create({});
I want to provide some dynamic call in popupWrapper, like this:
import popup from './PopupWrapper';
popup.open = () => {};
popup.close = () => {};
How can i defined open
and close
by Generics?
Besides,sometimes I don't want to defined the variables in data. I just want to defined a property in Vue instance. How can i defined _component
by Generics?
const portal = component({
methods: {
remove() {
this._component = null;
},
add() {
this._component = new Vue({});
},
},
});
Would like to thank your efforts for creating this package. It has made our project and vue components quite typesafe and we are very happy with it. The only thing missing for me is conditional directives. I know we can use ternary statements in the render() function but to me the conditional directives are great for reducing code clutter.
I have worked a bunch in react land and am using this babel plugin: https://github.com/peakchen90/babel-plugin-react-directives
I am wondering if this plugin could perhaps be integrated into the vue-tsx-support library or something similar.
Would be happy to give it a try myself and make a PR if I knew where to start.
In 2.1.1, using the below code:
export const VAvatar = ofType<Props, Events, ScopedSlots>().convert(
VueAvatarOriginal,
);
the type of VAvatar
is like the following:
const VAvatar: VueConstructor<{
_tsxattrs: TsxComponentAttrs<Props, Events, ScopedSlots>;
} & Vue>
but when I use with 2.2.0
the type of VAvatar
is like the following instead:
const VAvatar: VueConstructor<any>
It would be nice if we can open a wiki or something to help for migration process.
I just had a problem with onClick
. After some time, I noticed that I had to use onClick={() => this.close()}
instead of onClick={this.close()}
.
This was a dialog and I could not open it because it was closed automatically every time I wanted to open it.
like this:
const Tag = this.props.long ? "textarea" : "input"
const input = <Tag
onChange={this.props.onChange}
className="make-this-pretty"
id="important-input"
/>;
I see that @vue/babel-preset-jsx
uses v-on:eventName
or vOn:eventName
(see https://github.com/vuejs/jsx/tree/dev/packages/babel-sugar-v-on). But I guess this syntax is not supported in TSX because of the double column?
I currently use componentFactoryOf
with a methodonEventName()
and $emit("eventName")
and when I listen with onEventName={...}
, this works. But I'm trying to understand why. Are all attributes that start with on
put in the on
node data object?
Hello, I have a question in using vue-tsx-support. When I write a component, I need to complete an api function in a vue.
<input ...$listeners >
I was browsing the vue-tsx-support development documentation and found that it can be used
<Component {...{ nativeOn: {click: ...}}} />
So I changed the code to
<input type='text' value={ me.value} onInput={ (e) => me.$emit('input', e.target.value)} {...{ nativeOn: {...me .$listeners}} }>
But webpack has an error. Should I use this syntax, should I still need the relevant dependencies?
Hi there, I installed this wonderful tool via vue-cli
with the command vue add tsx-support
.
Everything seems to be working fine ; however, when I compile I have the following error:
ERROR in /home/......../node_modules/vue-tsx-support/enable-check.d.ts
13:13 Duplicate string index signature.
11 | interface IntrinsicElements extends base.IntrinsicElements {
12 | // allow unknown elements
> 13 | [name: string]: any;
| ^
14 |
15 | // builtin components
16 | transition: base.TsxComponentAttrs<builtin.TransitionProps>;
Version: typescript 3.3.4000
Any tips on how to get rid of it? Thanks!
In 2.1.1, using the below code:
export const VAvatar = ofType<Props, Events, ScopedSlots>().convert(
VueAvatarOriginal,
);
the type of VAvatar
is like the following:
const VAvatar: VueConstructor<{
_tsxattrs: TsxComponentAttrs<Props, Events, ScopedSlots>;
} & Vue>
but when I use with 2.2.0
the type of VAvatar
is like the following instead:
const VAvatar: VueConstructor<any>
Hello!
I've playing around your library and I am wondering if it is possible to use this with vue-class-component for better typechecking inside component code?
Button.tsx
import * as Vue from 'vue-tsx-support';
import Component from 'vue-class-component';
export interface ButtonEvents {
// Define the type of event handler like this,
// and use `?` to indicate whether the event is required.
// Will it be better?
onClick?: (e: MouseEvent, uid: number) => void;
}
@Component
export default class Button extends Vue.Component<{}, ButtonEvents> {
private readonly _uid!: number;
private handleClick(e: Event) {
this.$emit('click', e, this._uid);
}
render() {
return <button onClick={this.handleClick}>Button</button>;
}
}
App.tsx
import Vue from 'vue';
import Component from 'vue-class-component';
import Button from './Button';
@Component
export default class App extends Vue {
private handleClick(e: MouseEvent, uid: number) {
console.log(uid, e);
}
render() {
return <Button onClick={this.handleClick}>Click me</Button>;
}
}
The following isn't working
...
onKeyup={m.enter(this.addTodo)}
onKeyup={m.esc(this.addTodo)} // JSX can't have 2 onKeyup
...
Can we some how chain the modifiers? like onKeyup={m.enter.esc(this.addTodo)}
?
Hi,
I installed this using the vue cli plugin found here. Works great, except when running unit tests with Jest, I get this:
FAIL tests/unit/example.spec.ts
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/Users/lachlanmiller/javascript/vue/tsx/src/components/HelloWorld.tsx:7
return (<div>Ok</div>);
any ideas?
When I tried this:
<MyComponent v-for={row in this.rows} key={row.name} />
I get this error:
Cannot find name 'row'
Hi!
I have an error I can't seem to solve. I'd love some help! 😎
const PhaseComponent = getComponentOfPhase(phase)
const phaseComponent = <PhaseComponent {...{ props: phaseComponentProps }} />
getComponentOfPhase returns this:
the full getComponentOfPhase looks something like this, a "index.tsx" file that just returns the appropriate component based on a condition:
Version: 2.2.2
Argument of input's onInput callback must be InputHTMLAttributes type.
Actual behavior:
<input
onInput={e => console.log(e.target && e.target.value)}
// Property 'value' does not exist on type 'EventTarget'
/>
Expected behavior
<input
onInput={e => console.log(e.target.value)}
/>
Type '{ children: string; class: string; onClick: (event: any) => void; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes, HTMLSpanElement>'.
Property 'class' does not exist on type 'DetailedHTMLProps<HTMLAttributes, HTMLSpanElement>'.
14 | },
15 | render(): VNode {
16 | return <span class={ this.className } onClick={this.onClick}>{this.text};
| ^
17 | }
18 | });
How can I do either:
<MyComponent mode.sync={mode} />
or
<MyComponent mode={mode} on[mode:update]={val => this.mode = val} />
Currently, scopedSlots are defined to accept a function that returns VNodeChildrenArrayContents | string
:
// vnode.d.ts
export type ScopedSlot = (props: any) => VNodeChildrenArrayContents | string;
So, acoording to the type definition a scoped slot function always has to return an array:
// scopedSlot callback:
renderSlotContent( props: ScopeProps ) {
// must return array according to type definition:
return ( [ <span>asdadsf</span> ] );
},
But, it is also possible to directly return an element / node without wrapping it in array:
// scopedSlot callback:
renderSlotContent( props: ScopeProps ) {
// vue accepts this and it renders correctly
return <span>asdadsf</span>;
},
At the same time typescript complains about this, because it assumes that the return type must be VNodeChildrenArrayContents | string
.
Now, I have almost no knowledge about Vue render functions and VNodes and such...but why does the return type has to be an array? Is there a specific reason?
And, can that type definition be made more flexible so typescript stops complaining if the callback function returns a node directly (without wrapping it in an array)?
Thank you very much,
and thanks for this great library!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.