Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying required fields on Realm.Object #5000

Merged
merged 5 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Enhancements
* Add support for using functions as default property values, in order to allow dynamic defaults [#5001](https://github.com/realm/realm-js/pull/5001), [#2393](https://github.com/realm/realm-js/issues/2393)
* All fields of a `Realm.Object` treated as optional by TypeScript when constructing a new class-based model, unless specified in the second type parameter [#5000](https://github.com/realm/realm-js/pull/5000)

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?)
Expand Down
47 changes: 41 additions & 6 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,36 @@ declare namespace Realm {
type ObjectChangeCallback<T> = (object: T, changes: ObjectChangeSet<T>) => void;

/**
* Object
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Object.html }
* Base class for a Realm Object.
* @see
* {@link https://realm.io/docs/javascript/latest/api/Realm.Object.html}
*
* @example
* To define a class `Person` which requires the `name` and `age` properties to be
* specified when it is being constructed, using the Realm Babel plugin to allow
* Typescript-only model definitions (otherwise it would require a `static` schema):
* ```
* class Person extends Realm.Object<Person, "name" | "age"> {
* _id = new Realm.Types.ObjectId();
* name: string;
* age: Realm.Types.Int;
* }
* ```
*
* @typeParam `T` - The type of this class (e.g. if your class is `Person`,
* `T` should also be `Person` - this duplication is required due to how
* TypeScript works)
*
* @typeParam `RequiredProperties` - The names of any properties of this
* class which are required when an instance is constructed with `new`. Any
* properties not specified will be optional, and will default to a sensible
* null value if no default is specified elsewhere.
*/
abstract class Object<T = unknown> {
abstract class Object<T = unknown, RequiredProperties extends keyof OmittedRealmTypes<T> = never> {
/**
* Creates a new object in the database.
*/
constructor(realm: Realm, values: Unmanaged<T>);
constructor(realm: Realm, values: Unmanaged<T, RequiredProperties>);

/**
* @returns An array of the names of the object's properties.
Expand Down Expand Up @@ -1031,16 +1053,29 @@ type OmittedRealmTypes<T> = Omit<T,
ExtractPropertyNamesOfType<T, Realm.Dictionary>
>;

/** Make all fields optional except those specified in K */
type OptionalExcept<T, K extends keyof T> = Partial<T> & Pick<T, K>;

/**
* Omits all properties of a model which are not defined by the schema,
* making all properties optional except those specified in RequiredProperties.
*/
type OmittedRealmTypesWithRequired<T, RequiredProperties extends keyof OmittedRealmTypes<T>> =
OptionalExcept<OmittedRealmTypes<T>, RequiredProperties>;

/** Remaps realm types to "simpler" types (arrays and objects) */
type RemappedRealmTypes<T> =
RealmListsRemappedModelPart<T> &
RealmDictionaryRemappedModelPart<T>;

/**
* Joins T stripped of all keys which value extends Realm.Collection and all inherited from Realm.Object,
* with only the keys which value extends Realm.List, remapped as Arrays.
* with only the keys which value extends Realm.List, remapped as Arrays. All properties are optional
* except those specified in RequiredProperties.
*/
type Unmanaged<T> = OmittedRealmTypes<T> & RemappedRealmTypes<T>;
type Unmanaged<T, RequiredProperties extends keyof OmittedRealmTypes<T> = never> =
OmittedRealmTypesWithRequired<T, RequiredProperties> & RemappedRealmTypes<T>;

declare class Realm {
static defaultPath: string;

Expand Down