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

Not Assignable Types That Should Be #3672

Closed
pixelshaded opened this issue Jun 29, 2015 · 5 comments
Closed

Not Assignable Types That Should Be #3672

pixelshaded opened this issue Jun 29, 2015 · 5 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@pixelshaded
Copy link

I'm using angular-resource.d.ts

Type 'IResourceArray<IResource<ICompany>>' is not assignable to type 'IGridFilterOption[]'.
interface IResourceArray<T> extends Array<T> {
    /** the promise of the original server interaction that created this collection. **/
    $promise : angular.IPromise<IResourceArray<T>>;
    $resolved : boolean;
}
// Instance calls always return the the promise of the request which retrieved the object
// https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L538-L546
interface IResource<T> {
    $get(): angular.IPromise<T>;
    $get(params?: Object, success?: Function, error?: Function): angular.IPromise<T>;
    $get(success: Function, error?: Function): angular.IPromise<T>;

    $query(): angular.IPromise<IResourceArray<T>>;
    $query(params?: Object, success?: Function, error?: Function): angular.IPromise<IResourceArray<T>>;
    $query(success: Function, error?: Function): angular.IPromise<IResourceArray<T>>;

    $save(): angular.IPromise<T>;
    $save(params?: Object, success?: Function, error?: Function): angular.IPromise<T>;
    $save(success: Function, error?: Function): angular.IPromise<T>;

    $remove(): angular.IPromise<T>;
    $remove(params?: Object, success?: Function, error?: Function): angular.IPromise<T>;
    $remove(success: Function, error?: Function): angular.IPromise<T>;

    $delete(): angular.IPromise<T>;
    $delete(params?: Object, success?: Function, error?: Function): angular.IPromise<T>;
    $delete(success: Function, error?: Function): angular.IPromise<T>;

    /** the promise of the original server interaction that created this instance. **/
    $promise : angular.IPromise<T>;
    $resolved : boolean;
}
interface ICompany {
   id: number;
   name: string;
}
interface IGridFilterOption {
    id: number;
    name: string;
}

And this code has the line generating the error.

let companyPromise: IPromise<void> = this.companyService.getAll()
    .then((companies: IResourceArray<IResource<ICompany>>) => {
        let filter: IGridFilter = _.find(this.companyGridMetadata.filters, (f: IGridFilter) => {
            return f.name === 'Company';
        });
        filter.options = companies;
});

I feel like filter.options = companies should be valid. ICompany and IGridFilterOption have the same properties. IResource is simply a wrapper around ICompany that adds CRUD ops to it. IResourceArray extends Array by adding promise related properties.

Types of property 'push' are incompatible.
    Type '(...items: IResource<ICompany>[]) => number' is not assignable to type '(...items: IGridFilterOption[]) => number'.
      Types of parameters 'items' and 'items' are incompatible.
        Type 'IResource<ICompany>' is not assignable to type 'IGridFilterOption'.
          Property 'id' is missing in type 'IResource<ICompany>'.

What needs to be changed in the type definitions to make this assignment valid?

@pixelshaded pixelshaded changed the title Not Assignable Types Not Assignable Types That Should Be Jun 29, 2015
@pixelshaded
Copy link
Author

This is all I could come up with:

interface ICompanyResource extends ICompany, IResource<ICompany> {}

While this works, it feels highly inflexible. Anytime I wrap something with IResource and need to access properties on the generic, I would need to create another interface.

@RyanCavanaugh
Copy link
Member

Is it the case that something that is IResource<T> really does have all the members of T?

If so, it seems like intersection types (#3622) should be able to model this.

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Jul 14, 2015
@RyanCavanaugh
Copy link
Member

Closing for housekeeping reasons; feel free to comment in the future (we do watch closed issues)

@goleafs
Copy link

goleafs commented Nov 19, 2015

running into this now... just trying to have a generic service returning a promise of an array
but can't find a clean way to do this..

strange that this works...

        public get(id: number): ng.IPromise<T> {

            var promise = this.svc.get(id);

            var dfd: ng.IDeferred<T> = this.$q.defer();

            promise.then(function (tDto) {
                dfd.resolve(tDto);
            }, function (ex) {
                dfd.reject(ex);
            });

            return dfd.promise;
        }

but this does not

        public query(): ng.IPromise<Array<T>> {

            var promise = this.svc.query();

            var dfd: ng.IDeferred<Array<T>> = this.$q.defer();

            promise.then(function (tDto) {
                dfd.resolve(tDto);  // error!
            }, function (ex) {
                dfd.reject(ex);
            });

            return dfd.promise;
        }

@RyanCavanaugh
Copy link
Member

@goleafs can you get this to be a self-contained repro? There are many promise libraries floating around out there so it's hard for us to check these things locally.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants