-
-
Save ver-1000000/3d03a3e3d2c269cb5c450116c8e11407 to your computer and use it in GitHub Desktop.
import { Pipe, PipeTransform } from '@angular/core'; | |
/** | |
* `{ id: number, name: string }[]`のような、ユニークな値を持つオブジェクトの配列に対して、 | |
* 簡単に{@link https://angular.io/api/core/TrackByFunction TrackByFunction}を設定するためのパイプ。 | |
* | |
* @example | |
* <!-- `{ id: number, name: string }[]` --> | |
* <div *ngFor="let item of items; trackBy: 'id' | keyTrackBy">{{ item.id }}: {{ item.name }}</div> | |
* | |
* <!-- `{ id: number | null, name: string | null }[]` --> | |
* <input name="name" [(ngModel)]="item.name" *ngFor="let item of items; trackBy: null | keyTrackBy"> | |
*/ | |
@Pipe({ name: 'keyTrackBy' }) | |
export class KeyTrackByPipe implements PipeTransform { | |
transform<T>(key: null | keyof T): (_: number, item: T) => T | T[keyof T] { | |
return (_: number, item: T) => key == null ? item : item[key]; | |
} | |
} |
これってtemplate側で型チェック効きますか?
Angular 8.2.11で、以下のようなコードを用いて確認してみました。
<!-- items = [{ id: 1, name: 'a' }, { id: 2, name: 'a' }, { id: 3, name: 'a' }, { id: 4, name: 'a' }]; -->
{{ ('id' | keyTrackBy)(1, items[0]) }}
keyTrackByの引数('id'
)はvscode(Angular Language Service/Javascript and TypeScript Nightly導入)とvim(ALE導入)では補完されず、また、'id'
ではなくnull
や1
を入れても型警告を出しませんでした。
しかし、引数にtypeof Item
ではない値('hoge'
)を入れてaotビルドしてみたところ、型エラー出してくれました。
Ivyになったらよさそうですね。
TrackByFunction のリターンは
item[key] || item;
でもいいかもしれないと思いました。
エラーを握り潰すみたいな話になるかもしれませんが。
これは私も思ったのですが、使うときのことを考えると「自身返すようにしたい時、nullいれんの?空文字いれんの?undefinedいれんの?falseいれんの?」みたいな話が出てきて、そういう揺れがプロジェクト内にはびこるのも嫌だなぁ、と。。。(Prettierとかで制限できんのかな?テンプレートは無理か)(keyがnullのオブジェクトとかも作れっちゃ作れるからそこらへん考慮するとやはり設計に気持ち悪さが残る)
あとはまぁこれしないほうが型が厳密っていう話もありますね。
でも…… TeaTwoさんがおっしゃるならこの実装もアリかな〜〜って気持ちになってきたのでのちのちこうするかも。 やっぱり毎回trackByFn書くの嫌すぎなんで……。
ちょっと書きなおしてみたんですけど割といいかもしれない!?
そもそもキーにnull設定とかしねぇだろがよォって話ですしこうしようかな!!!
trackByに関数参照で渡すため、ジェネリクス指定できない状態なので難しそうだなと思ってました。
someArray.map(someFunction<Hoge>) ←できない
パイプを実行記述して、かつ引数itemをngForでイテレータされたitemじゃなくて、元のコレクションの添字指定にすると、AoTで検出できるんですね。
ngForでイテレータされたitemだと検出できないのは、バグっぽいですね...。
ts、型推論がいい感じにやってくれるのでいいですね〜。
ngForでイテレータされたitemだと検出できないのは、バグっぽいですね...。
これはどういうことだろう、できるのでは……? ngForの中で使っても同じかと思いますよ。(↑の確認コード、ngFor内で行わなかったのは、わかりにくいかなぁ〜と思ってのことでした。 逆にわかりにくくなってしまったのかな!?)
手元でやっているとそういう結果になるんですけど、AoTで検出できてます?
*ngFor of
はショートカットで内部的にはAngularがごにょごにょ展開してるから難しいのかなあと勝手に忖度してました!
ありがとうございます。条件・環境の何かの違いでできる場合あるのかな?と気になってたので、スッキリしました!
展開コードまでみないとダメな理由わからなさそうだな……。
ngc
の出力結果でわかりそうですが、追うの辛いw
transformの返り値としてTrackByFunctionみたいなものを返すようにしていたけど、どうしてもうまくいかないので関数を返す型をそのまま書いた……。 これによって、存在しないキーを指定したりできないようになったと思う。
型マスターが助言してくれたら嬉しい……。
ちなみに、↑のteatwoさんとのやり取りの問題はいつの間にか解消していたようです? 普通に推論効いてるっぽいです
これってtemplate側で型チェック効きますか?
TrackByFunction のリターンは
item[key] || item;
でもいいかもしれないと思いました。エラーを握り潰すみたいな話になるかもしれませんが。