4

マップからエントリを取得し、まだ存在しない場合は追加するためのヘルパー関数があります。

export function mapGetOrCreate<K, V>(map: Map<K, V>, key: K, valueFn: (key: K) => V): V {
    let value = map.get(key);
    if (value === undefined) {
        value = valueFn(key);
        assert(value !== undefined);
        map.set(key, value);
    }
    return value;
}

( TS プレイグラウンドの完全なコード)

ジェネリック型の差異に関する TypeScript の不健全さは、私にとってこの実際的な問題を引き起こします。

type A = {a: number};
type B = A & {b: string};
type C = B & {c: boolean};

declare function createA(): A;
declare function createB(): B;
declare function createC(): C;

function f(m: Map<string, B>, element: Base) {
    m.set('1', createA()); // TS error (good)
    m.set('1', createB());
    m.set('1', createC());

    mapGetOrCreate(m, '1', createA); // missing error!
    mapGetOrCreate(m, '1', createB);
    mapGetOrCreate(m, '1', createC);
}

別の型パラメーター ( V2) を関数シグネチャに追加すると、問題が「修正」されることがわかりました。

export function mapGetOrCreate2<K, V, V2 extends V>(map: Map<K, V>, key: K, valueFn: (key: K) => V2): V {
    let value = map.get(key);
    if (value === undefined) {
        value = valueFn(key);
        assert(value !== undefined);
        map.set(key, value);
    }
    return value;
}

まだ不健全ですが、少なくとも TypeScript は型を自動的に推測できません。これはわずかな改善です。

質問:

  1. 私がやっていることを達成するためのより良い方法はありますか?
  2. mapGetOrCreate2オリジナルより悪い方法はありますか?
4

1 に答える 1