typescript - Bir özelliğin başka bir tipte var olup olmadığına bağlı olarak tipleri nasıl koşullu olarak seçebilirim?
Öncelikle, aşağıdaki sonucu istiyorum:
type Wrapper<ID extends string> = { id: ID };
type WrapperWithPayload<ID extends string, Payload> = { id: ID, payload: Payload };
enum IDs {
FOO = "ID Foo",
BAR = "ID Bar",
BAZ = "ID Baz"
}
interface AssociatedTypes {
[IDs.FOO]: number;
[IDs.BAR]: number[];
}
type Result = MagicMapper<IDs, AssociatedTypes>
/*
* Result should have this type:
* {
* [IDs.FOO]: WrapperWithPayload<IDs.FOO, number>;
* [IDs.BAR]: WrapperWithPayload<IDs.BAR, number[]>;
* [IDs.BAZ]: Wrapper<IDs.BAZ>;
* }
*/
Başka bir deyişle, bazı dizeleri ve bu dizelerin alt kümesini başka bir türe eşleyen bir eşlemeyi sağlamak istiyorum. Sonra, dizeleri anahtar olarak kullanarak yeni bir tür oluşturmak istiyorum. Dizelerin/anahtarların her biri için, bir eşleme varsa tür A'yı, yoksa tür B'yi kullanmak istiyorum.
Şu anda yaklaşımım şöyle görünüyor:
type MagicMapper<T extends string, Mapping extends { [key in T]?: any }> = {
[key in T]: Mapping[key] extends never ? Wrapper<key> : WrapperWithPayload<key, Mapping[key]>;
};
Ve o neredeyse golü vuruyor:
type Result = {
"ID Foo": WrapperWithPayload<IDs.FOO, number>;
"ID Bar": WrapperWithPayload<IDs.BAR, number[]>;
"ID Baz": Wrapper<IDs.BAZ> | WrapperWithPayload<IDs.BAZ, any>;
}
Baz anahtarı üzerindeki birleşim yanlış. Sanırım hata extends never koşulunda yatıyor, ancak bunu örneğin undefined ile değiştirmek işleri sadece daha kötü yapıyor:
type MagicMapper<T extends string, Mapping extends { [key in T]?: any }> = {
[key in T]: Mapping[key] extends undefined ? Wrapper<key> : WrapperWithPayload<key, Mapping[key]>;
};
type Result = {
"ID Foo": Wrapper<IDs.FOO>;
"ID Bar": Wrapper<IDs.BAR>;
"ID Baz": Wrapper<IDs.BAZ>;
}
İşlerin benim ihtiyacım olan şekilde ilerlemesini sağlamanın bir yolu var mı?
Cevap #1
Mapping içindeki anahtarın varlığını test etme şeklini Mapping extends { [P in key]: infer U } olarak değiştirebilirsiniz ve her şey beklendiği gibi çalışacaktır:
type Wrapper<ID extends string> = { id: ID };
type WrapperWithPayload<ID extends string, Payload> = { id: ID, payload: Payload };
enum IDs {
FOO = "ID Foo",
BAR = "ID Bar",
BAZ = "ID Baz"
}
interface AssociatedTypes {
[IDs.FOO]: number;
[IDs.BAR]: number[];
}
type MagicMapper<T extends string, Mapping extends { [key in T]?: any }> = {
[key in T]: Mapping extends { [P in key]: infer U } ? WrapperWithPayload<key, U>: Wrapper<key> ;
};
type Result = MagicMapper<IDs, AssociatedTypes>
// same as :
type Result = {
"ID Foo": WrapperWithPayload<IDs.FOO, number>;
"ID Bar": WrapperWithPayload<IDs.BAR, number[]>;
"ID Baz": Wrapper<IDs.BAZ>;
}
Oyun alanı linki
