Skip to content

Instantly share code, notes, and snippets.

@Kesin11
Created December 16, 2018 09:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kesin11/47d8c90fcbe35cbc147d91c4a406a89f to your computer and use it in GitHub Desktop.
Save Kesin11/47d8c90fcbe35cbc147d91c4a406a89f to your computer and use it in GitHub Desktop.
TypeScriptのGenericsの習作
interface CollectionSchema {
_proto: any
path: string
sub ?: {
[prop: string]: CreateCollection<any> ,
}
}
type CreateCollection<T> = (parentPath: string) => Collection<T extends CollectionSchema ? T: never>
class Collection<T extends CollectionSchema> {
public path: string
public sub?: {
[Key in keyof T['sub']]: CreateCollection<any>;
}
constructor (path: string, sub?: {[Key in keyof T['sub']]: CreateCollection<any>}) {
this.path = path
this.sub = sub
}
public fetch (): T['_proto'] {
// 実際はFirestoreからフェッチしたオブジェクトを返す
return { id: 1, name: 'dummy' } as T['_proto']
}
public subcollection<Key extends keyof T['sub']> (key: Key): T['sub'][Key] | undefined {
if (this.sub) return this.sub[key] as unknown as T['sub'][Key]
return
}
}
// ここからCollectionを使う側のコード
interface User {
id: number,
name: string,
}
interface Book {
id: number,
title: string
}
interface MySchema {
_proto: User // 実装コードには不要だが、型を推論するために型の世界でどうしても必要
path: string
sub: {
friend: CreateCollection<UserSchema>
book: CreateCollection<BookSchema>,
}
}
interface UserSchema {
_proto: User
path: string
}
interface BookSchema {
_proto: Book,
path: string
}
const userCollection = new Collection<MySchema>(
'user',
{
// サブコレクションは本当は↓のようなパスになるので、
// parentの情報を入れてCollectionを作る必要があるのでparentPathを受け取っているが、今は省略
// user/{user_id}/friend/{user_friend_id}
// user/{user_id}/book/{user_book_id}
friend: (parentPath: string) => new Collection<UserSchema>('friend'),
book: (parentPath: string) => new Collection<BookSchema>('book'),
},
)
const userBookCollection = userCollection.subcollection('book')!('alice') // Collection<BookSchema>
const userBook = userBookCollection.fetch() // Bookと推論されたので完成
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment