LoginSignup
1
2

More than 5 years have passed since last update.

AngularJS1.x系の$resource型問題を素敵に解消する

Posted at

$resource型問題

素のjavascriptで書いてる場合ならこの対応で問題無いが、

var notes = $resource('/notes/:id', null, {
  'update': { method:'PUT' }
});

TypeScriptの場合はng.resource.IResourceClass<T>型の制約でupdateなんてメソッド無いぞボケって怒られてしまうよね。

this.getResource('publish').update({},
    project,
    ()=> {
        success()
    },
    (e)=> {
        error ? error() : null
    }
)

するとこのようにanyへの変換を強いられ型って一体なんだっけ?という気持ちになる。

(this.getResource('delete') as any).update({},
    project,
    ()=> {
        success()
    },
    (e)=> {
        error ? error() : null
    }
)

解決方法

この問題を解消するためにresourceクラスの基底クラスにng.resource.IResourceClass<T>型を拡張して返すFactoryメソッドを定義するというアプローチを取りました。
(といいつつ内部でanyへの変換をしています。。。いい方法あるかな?)

resource.ts
// extendsしてupdateメソッドを定義する
export interface IResourceClass<T> extends ng.resource.IResourceClass<T> {
    update: angular.resource.IResourceMethod<T>;
}

export default class Resource<T> {
    constructor(protected resource: ng.resource.IResourceService,
                protected path: string) {
    }

    protected getResource(query?: string): IResourceClass<T> {
        // 結局ここはany変換してしまった。。。
        return <any>this.resource(`/api/${this.path}` + (query ? `/${query}` : ''), null, {
            'update': { method:'PUT' }
        })
    }
}

使い方

user.ts
export default class UserResource extends Resource<User> {
    static $inject = ['$resource']
    constructor(protected resource: ng.resource.IResourceService) {
        super(resource, 'users')
    }

    // 'GET /api/users/:userId'
    get(userId: string, success: (user: User)=>void, error?: ()=> void) {
        let res = this.getResource(':userId').get({
                userId: userId
            },
            ()=> {
                success(res)
            },
            (e)=> {
                error ? error() : null
            }
        )
    }

    // 'GET /api/users'
    list(success: (users: Array<User>)=> void, error?: ()=> void) {
        let res = this.getResource().query({},
            ()=> {
                success(res)
            },
            (e)=> {
                error ? error() : null
            }
        )
    }

    // GET /api/users/search'
    search(condition: User, success: (users: Array<User>)=> void, error?: ()=> void) {
        this.getResource('search').query(
            condition,
            ()=> {
                success()
            },
            (e)=> {
                error ? error() : null
            }
        )
    }

    // POST /api/users'
    create(user: User, success: (user: User)=> void, error?: ()=> void) {
        this.getResource().save({},
            user,
            ()=> {
                success(user)
            },
            ()=> {
                error ? error() : null
        })
    }

    // PUT /api/users'
    save(id: number,user: User, success: ()=> void, error?: ()=> void) {
        this.getResource().update({
                id: id
            },
            user,
            ()=> {
                success()
            },
            ()=> {
                error ? error() : null
            })
    }

    // DELETE /api/users'
    delete(user: User, success: ()=> void, error?: ()=> void) {
        this.getResource().delete({},
            user,
            ()=> {
                success()
            },
            (e)=> {
                error ? error() : null
            }
        )
    }
}

あまりTypeScript版のサンプルが落ちていないのと、日本語情報を見かけないのでメモをば。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2