Skip to content

Commit

Permalink
ts: require optional fields in create() and mark instances as Required
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyraspopov committed Apr 18, 2024
1 parent d2be8b5 commit 60c98b8
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ISC License

Copyright (c) 2017-2022 Alexey Raspopov
Copyright (c) 2017-2024 Oleksii Raspopov

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "dataclass",
"version": "2.1.1",
"version": "3.0.0-beta.0",
"description": "Data classes for TypeScript & JavaScript",
"author": "Alexey Raspopov",
"author": "Oleksii Raspopov",
"license": "ISC",
"homepage": "https://dataclass.js.org",
"repository": "alexeyraspopov/dataclass",
Expand All @@ -14,6 +14,7 @@
"dataclass.*"
],
"keywords": [
"dataclass",
"immutable",
"value-objects",
"data-structures",
Expand Down
71 changes: 68 additions & 3 deletions typings/dataclass.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,73 @@
type Optional<T> = { [P in keyof T as T[P] extends Exclude<T[P], undefined> ? never : P]: T[P] };
type Explicit<T> = { [P in keyof T as T[P] extends Exclude<T[P], undefined> ? P : never]: T[P] };
type Init<T> = Required<Optional<Omit<T, keyof Data>>> & Partial<Explicit<Omit<T, keyof Data>>>;

/**
* Abstract class that allows defining custom data classes. Should be extended
* with a set of class fields that define the shape of desired model.
*
* ```ts
* import { Data } from "dataclass";
*
* class Project extends Data {
* // this property is required when creating an instance
* id?: string;
* // these properties have defaults but can be overwritten
* name: string = "Untitled";
* createdBy: string = "Anon";
* // this property may contain null and won't be required
* createdAt: Date | null = null;
* }
*
* let project = Project.create({
* id: 'abc123',
* createdBy: 'Oleksii',
* });
* // > Project { id: 'abc123', name: 'Untitled', createdBy: 'Oleksii', createdAt: null }
* ```
*
* @link https://dataclass.js.org
*/
export class Data {
/**
* Instantiate the data class. Provide custom values that should override
* defaults. If the class has optional properties, create() method will
* require to explicitly define them.
*
* ```ts
* class User extends Data {
* name: string = "Anon";
* age: number | null = null;
* }
* ```
*
* @link https://dataclass.js.org/guide/getting-started.html
*/
static create<Type extends Data>(
this: { new (): Type },
values?: Omit<Partial<Type>, keyof Data>,
): Type;
copy(values?: Omit<Partial<this>, keyof Data>): this;
...values: Optional<Type> extends Record<any, never> ? [Init<Type>?] : [Init<Type>]
): Required<Type>;
/**
* Create new immutable instance based on existing one, with some properties changed.
*
* ```ts
* class User extends Data {
* name: string = "Anon";
* age: number | null = null;
* }
*
* let initial = User.create({ name: "Liza" });
*
* // creates an immutable copy with previously defined
* // `name: "Liza"` and additionaly defined `age: 28`
* let updated = initial.copy({ age: 28 });
* ```
*/
copy(values?: Partial<Omit<this, keyof Data>>): Required<this>;
/**
* Compare the instance to another instance of the same data class.
*
* @link https://dataclass.js.org/guide/objects-equality.html
*/
equals(other: this): boolean;
}

0 comments on commit 60c98b8

Please sign in to comment.