realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.62k stars 558 forks source link

Typescript: realm.objects(... doesn't return Realm.Results #6213

Closed angelos3lex closed 2 months ago

angelos3lex commented 6 months ago

How frequently does the bug occur?

Always

Description

Imagine i have the following code:

import Realm from 'realm';
public createQuery<T>(schema: string): Realm.Results<T> {
    return this._realm.objects(schema);
}

This growls (typescript 4.8.4) saying:

Type 'Results<RealmObject<T, never> & T>' is not assignable to type 'ResultsType<T>'.
  Types of property 'update' are incompatible.
    Type '(propertyName: ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>, value: Unmanaged<...>[ExtractPropertyN...' is not assignable to type '(propertyName: ExtractPropertyNamesOfType<T, AnyDictionary> | Exclude<keyof T, keyof AnyRealmObject | ExtractPropertyNamesOfType<T, AnyDictionary> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ExtractPropertyNamesOfType<...>, value: Unmanaged<...>[ExtractPropertyNamesOfType<...> | ... 1 more...'.
      Types of parameters 'propertyName' and 'propertyName' are incompatible.
        Type 'ExtractPropertyNamesOfType<T, AnyDictionary> | Exclude<keyof T, keyof AnyRealmObject | ExtractPropertyNamesOfType<T, AnyDictionary> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ExtractPropertyNamesOfType<...>' is not assignable to type 'ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>'.
          Type 'ExtractPropertyNamesOfType<T, AnyDictionary>' is not assignable to type 'ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>'.
            Type 'keyof T' is not assignable to type 'ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>'.
              Type 'string | number | symbol' is not assignable to type 'ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>'.
                Type 'string' is not assignable to type 'ExtractPropertyNamesOfType<RealmObject<T, never> & T, AnyDictionary> | Exclude<"keys", keyof AnyRealmObject | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...> | ExtractPropertyNamesOfType<...>> | ... 13 more ... | ExtractPropertyNamesOfType<...>'.ts(2322)

If i do:

import Realm, {Results} from 'realm';
public createQuery<T>(schema: string): Results<T> {
    return this._realm.objects(schema);
}

I get ts error: Type 'Results' is not generic. ts(2315)

According to the docs, it should be valid the Realm.Results type

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

No response

Version

12.2.0

What services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

android, iOS

Build environment

RN Version 0.72.5

Cocoapods version

No response

takameyer commented 6 months ago

@angelos3lex What about:

import Realm, {Results} from 'realm';
public createQuery<T>(schema: string): Results<T> {
    return this._realm.objects<T>(schema); // <- forward the generic
}

Does that work?

angelos3lex commented 6 months ago

@angelos3lex What about:

import Realm, {Results} from 'realm';
public createQuery<T>(schema: string): Results<T> {
    return this._realm.objects<T>(schema); // <- forward the generic
}

Does that work?

If i use the Results i always get the error: Type 'Results' is not generic.ts(2315) That's why i use the Realm.Results but then i get the error i sent above. Even if i propagate the <T> inside this._realm.objects<T>(schema);

tuantvk commented 3 months ago

@angelos3lex same issue I tried import Results from @realm/react it worked for me and I don't know why it is different when import from realm or @realm/react also I had checked in @realm/react it's the same thing.

import { Realm, useQuery } from "@realm/react"

const getIcons = (icons: Realm.Results<Icon>) => {
// ...
}

const data = useQuery(....)
const icons = getIcons(data)

Your case:

import { Realm, useRealm } from "@realm/react"

const createQuery = <T>(schema: string): Realm.Results<Realm.Object<T> & T> => {
  const realm = useRealm()
  return realm.objects<T>(schema)
}

const icons = createQuery<Icon>("Icon")
icons.filtered('name TEXT $0', 'hunger')
kneth commented 2 months ago

I wonder if

import Realm, {Results} from 'realm';
public createQuery<T extends Realm.Object>(schema: string): Results<T> {
    return this._realm.objects<T>(schema); 
}

will be useful

elle-j commented 2 months ago

@angelos3lex, the following should work for you:

import Realm from 'realm';

// ...

public createQuery<T>(schema: string): Realm.Results<RealmObject<T> & T> {
  return this._realm.objects(schema);
}