vue-ts-types
Lightweight TypeScript-first Vue prop type definitions

Example
import { defineComponent } from 'vue';
import {
arrayProp,
booleanProp,
functionProp,
isPositive,
numberProp,
oneOfProp,
stringProp,
} from 'vue-ts-types';
defineComponent({
props: {
disabled: booleanProp().withDefault(false),
title: stringProp().optional,
description: stringProp().nullable,
items: arrayProp<string>().required,
callback: functionProp<() => void>().optional,
color: oneOfProp(['red', 'green', 'blue'] as const).withDefault('red'),
timeout: numberProp(isPositive).required,
},
});
Motivation
Prop declarations are verbose
Declaring props is quite verbose, especially if you are using TypeScript and want to annotate more complex types (with PropType).
options: {
type: Object as PropType<Options>,
required: true,
}
options: objectProp<Options>().required
Annotating optional complex props is error-prone
It's easy to forget using a union type with undefined or null when the prop is not required.
options: {
type: Object as PropType<Options>,
required: false,
}
options: objectProp<Options>().optional
Specifying both default and required can be contradictory
By specifying a prop's default value, the prop is automatically optional, even when required is set to true. See also the vue/no-required-prop-with-default ESLint rule.
disabled: {
type: Boolean,
required: true,
default: false,
}
disabled: booleanProp().required
disabled: booleanProp().withDefault(false)
Custom validation errors are not helpful
Since prop validators return only a boolean validation result, the reason why a value failed to validate is not printed in the console error.
age: {
type: Number,
required: true,
validator: (age: unknown) => {
return typeof age === 'number' && Number.isInteger(age) && age >= 18
},
}
age: integerProp((age: unknown) => {
if (typeof age !== 'number' || age < 18) {
return 'age should be a number of at least 18'
}
return undefined
}).required
Installation
npm install vue-ts-types
vue-ts-types has no dependencies and is tested to be compatible with Vue.js v2.6, v2.7 and v3.2.
Usage
Each of the prop functions returns an object with the following properties:
.optional: Use this to mark the prop as not required with a default value of undefined. Also includes undefined in the resulting prop type.
.nullable: Use this to mark the prop as not required with a default value of null. Also includes null in the resulting prop type.
.required: Use this to mark the prop as required without a default value.
.withDefault(value): Use this to set a default value for the prop. Note that the value has to fit the prop type. For non-primitive types, the value has to be a function that returns the default value.
ℹ️ Note:
Due to the way Vue props work, a prop's default value will only be used when passing undefined, not for null.
See issue #3135 in vuejs/vue.
Custom validator functions
Custom validator functions can be passed to any of the prop types. They are called with the value of the prop (type unknown) and should return a validation error message, or undefined if the value is valid. Validator functions do not influence type inference.
import { numberProp } from 'vue-ts-types';
type Validator = (value: unknown) => string | undefined;
const isPositive: Validator = (value) => {
if (typeof value !== 'number' || value <= 0 || Number.isNaN(value)) {
return 'value should be a positive number';
}
return undefined;
};
numberProp(isPositive).optional;
For convenience, some common validator functions are included in the library and can be imported just like prop types:
isNegative: only allows negative numbers (< 0)
isPositive: only allows positive numbers (> 0)
isNonNegative: only allows non-negative numbers (>= 0)
isNonPositive: only allows non-positive numbers (<= 0)
stringProp<T>(validator?: Validator)
Allows any string. No further runtime validation is performed by default.
Type parameter T can be used to restrict the type at compile time with a union type. (Consider using oneOfProp in this case.)
stringProp().optional;
stringProp().nullable;
stringProp().required;
stringProp().withDefault('foo');
type Foo = 'a' | 'b' | 'c';
stringProp<Foo>().optional;
stringProp<Foo>().nullable;
stringProp<Foo>().required;
stringProp<Foo>().withDefault('a');
booleanProp(validator?: Validator)
Allows any boolean (validated at runtime and compile time).
booleanProp().optional;
booleanProp().nullable;
booleanProp().required;
booleanProp().withDefault(false);
numberProp<T>(validator?: Validator)
Allows any number (validated at runtime and compile time).
Type parameter T can be used to restrict the type at compile time with a union type. (Consider using oneOfProp in this case.)
numberProp().optional;
numberProp().nullable;
numberProp().required;
numberProp().withDefault(3.1415);
type Foo = 1 | 2 | 3;
numberProp<Foo>().optional;
numberProp<Foo>().nullable;
numberProp<Foo>().required;
numberProp<Foo>().withDefault(1);
integerProp(validator?: Validator)
Allows any integer (validated at runtime).
integerProp().optional;
integerProp().nullable;
integerProp().required;
integerProp().withDefault(42);
dateProp(validator?: Validator)
Allows any Date object (validated at runtime and compile time).
dateProp().optional;
dateProp().nullable;
dateProp().required;
dateProp().withDefault(() => new Date());
symbolProp(validator?: Validator)
Allows any symbol (validated at runtime and compile time).
symbolProp().optional;
symbolProp().nullable;
symbolProp().required;
symbolProp().withDefault(Symbol('foo'));
vueComponentProp(validator?: Validator)
Allows any Vue component instance, name or options object. No built-in runtime validation is performed by default.
vueComponentProp().optional;
vueComponentProp().nullable;
vueComponentProp().required;
vueComponentProp().withDefault('close-icon');
ℹ️ Note:
The type VueComponent is defined to be object | string. It has to be so broad to allow Vue 2 and Vue 3 component options or instances.
If you are able to narrow the type without pulling in heavy dependencies, please open an issue or pull request!
anyProp<T>(validator?: Validator)
Allows any type. No built-in runtime validation is performed by default.
Type parameter T can be used to restrict the type at compile time.
anyProp().optional;
anyProp().nullable;
anyProp().required;
anyProp().withDefault('foo');
anyProp<string>().optional;
anyProp<string>().nullable;
anyProp<string>().required;
anyProp<string>().withDefault('foo');
arrayProp<T>(validator?: Validator)
Allows any array. No further runtime validation is performed by default.
Type parameter T can be used to restrict the type of the array items at compile time.
arrayProp().optional;
arrayProp().nullable;
arrayProp().required;
arrayProp().withDefault(() => []);
arrayProp<string>().optional;
arrayProp<string>().nullable;
arrayProp<string>().required;
arrayProp<string>().withDefault(() => ['foo', 'bar']);
objectProp<T>(validator?: Validator)
Allows any object. No further runtime validation is performed by default.
Type parameter T can be used to restrict the type at compile time.
objectProp().optional;
objectProp().nullable;
objectProp().required;
objectProp().withDefault(() => ({}));
interface User {
name: string;
}
objectProp<User>().optional;
objectProp<User>().nullable;
objectProp<User>().required;
objectProp<User>().withDefault(() => ({ name: 'John' }));
functionProp<T>(validator?: Validator)
Allows any function. No further runtime validation is performed by default.
Type parameter T can be used to restrict the type to a specific function signature at compile time.
ℹ️ Note:
There is no .withDefault() function for this prop type.
functionProp().optional;
functionProp().nullable;
functionProp().required;
type MyFunc = (a: number, b: string) => boolean;
functionProp<MyFunc>().optional;
functionProp<MyFunc>().nullable;
functionProp<MyFunc>().required;
oneOfProp<T>(allowedValues: readonly any[], validator?: Validator)
Allows any of the specified allowed values (validated at runtime and compile time).
Type parameter T can be used to adjust the inferred type at compile time, this is usually not necessary.
ℹ️ Note:
Proper type checking is only possible if the allowed values are readonly, usually through as const.
oneOfProp(['foo', 'bar'] as const).optional;
oneOfProp(['foo', 'bar'] as const).nullable;
oneOfProp(['foo', 'bar'] as const).required;
oneOfProp(['foo', 'bar'] as const).withDefault('foo');
oneOfObjectKeysProp<T>(object: object, validator?: Validator)
Allows any of the keys of the specified object (validated at runtime and compile time).
Type parameter T can be used to adjust the inferred type at compile time, this is usually not necessary.
oneOfObjectKeysProp({ foo: 1, bar: 2 }).optional;
oneOfObjectKeysProp({ foo: 1, bar: 2 }).nullable;
oneOfObjectKeysProp({ foo: 1, bar: 2 }).required;
oneOfObjectKeysProp({ foo: 1, bar: 2 }).withDefault('foo');
oneOfTypesProp<T>(type: PropType<T>, validator?: Validator)
Allows any of the passed constructor types (validated at runtime).
Type parameter T has to be used to adjust the type at compile time.
oneOfTypesProp<number | string>([Number, String]).optional;
oneOfTypesProp<number | string>([Number, String]).nullable;
oneOfTypesProp<number | string>([Number, String]).required;
oneOfTypesProp<number | string>([Number, String]).withDefault(42);
instanceOfProp<T>(parent: T, validator?: Validator)
Allows instances of the given constructor (validated at runtime and compile time).
Type parameter T can be used to adjust the inferred type at compile time.
instanceOfProp(Date).optional;
instanceOfProp(Date).nullable;
instanceOfProp(Date).required;
instanceOfProp(Date).withDefault(() => new Date());
Contributing
Please see CONTRIBUTING.md.
Similar packages
License
Unless otherwise noted, all source code is licensed under the MIT License.
Copyright (c) 2022 Flo Edelmann