НОВЫЙ ОТВЕТ:
Хорошо, я переключаю это: ваш DTO - это интерфейс, соответствующий обычным-старым - javascript -объектам, которые вы получаете из своего API:
interface SourceOfAddressDto {
sourceOfAddressId?: number | undefined;
sourceOfAddressCode?: string | undefined;
sourceOfAddressDescription?: string | undefined;
sourceOfAddressLabel?: string | undefined;
createDate: Date;
userId: string;
}
И ваш Lookup - это настоящий класс с методами, которые вам нужно использовать, например, shout()
, который я приведу в качестве примера:
class SourceOfAddressLookup {
sourceOfAddressId?: number | undefined;
sourceOfAddressCode?: string | undefined;
sourceOfAddressDescription?: string | undefined;
sourceOfAddressLabel?: string | undefined;
shout() {
console.log("HELLO MY ID IS " + this.sourceOfAddressId +
" AND MY CODE IS \"" + this.sourceOfAddressCode + "\"" +
" AND MY DESCRIPTION IS \"" + this.sourceOfAddressDescription + "\"" +
" AND MY LABEL IS \"" + this.sourceOfAddressLabel + "\"!");
}
}
Вместо pluck()
, как прежде Я определю assignProps()
, который принимает целевой объект, исходный объект и список ключей свойств для копирования из источника в место назначения. Это generic c, поэтому компилятор должен кричать на вас, если по какой-то причине свойства источника не соответствуют типу назначения:
function assignProps<T, K extends keyof T>(
destination: T,
source: Pick<T, K>,
...keys: K[]
): T {
keys.forEach(k => destination[k] = source[k]);
return destination;
}
Итак, mapFromSourceOfAddressDto
принимает SourceOfAddressDto
и вызывает assignProps()
на только что созданном экземпляре SourceOfAddressLookup
:
const mapFromSourceOfAddressDto = (dto: SourceOfAddressDto) => assignProps(
new SourceOfAddressLookup(),
dto,
"sourceOfAddressId",
"sourceOfAddressCode",
"sourceOfAddressDescription",
"sourceOfAddressLabel"
)
Компилируется без ошибок, поэтому типы должны работать. Затем вы можете довольно просто выполнить сопоставление массива, например:
class Foo {
public addressSourceList: Array<SourceOfAddressLookup>;
constructor(addressSourceListDto: Array<SourceOfAddressDto>) {
this.addressSourceList = addressSourceListDto.map(mapFromSourceOfAddressDto);
}
}
И давайте проверим это, построив что-то с массивом объектов SourceOfAddressDto
:
const foo = new Foo([{
createDate: new Date(),
userId: "abc",
sourceOfAddressId: 0,
sourceOfAddressDescription: "d",
sourceOfAddressCode: "c",
sourceOfAddressLabel: "l"
}, {
createDate: new Date(),
userId: "def",
sourceOfAddressId: 1,
sourceOfAddressDescription: "D",
sourceOfAddressCode: "C",
sourceOfAddressLabel: "L"
}]);
Это должно быть отображено с помощью Конструктор Foo
для массива SourceOfAddressLookup
экземпляров, поэтому давайте проверим его, вызвав метод shout()
для каждого элемента:
foo.addressSourceList.forEach(x => x.shout())
// HELLO MY ID IS 0 AND MY CODE IS "c" AND MY DESCRIPTION IS "d" AND MY LABEL IS "l"!
// HELLO MY ID IS 1 AND MY CODE IS "C" AND MY DESCRIPTION IS "D" AND MY LABEL IS "L"!
Хорошо, выглядит хорошо. Удачи снова!
Ссылка на игровую площадку с кодом
СТАРЫЙ ОТВЕТ:
Я предполагаю, что ваш DTO является полноценным классом с методы
class SourceOfAddressDto {
sourceOfAddressId: number | undefined;
sourceOfAddressCode: string | undefined;
sourceOfAddressDescription: string | undefined;
sourceOfAddressLabel: string | undefined;
createDate: Date;
userId: string;
constructor(createDate: Date, userId: string) {
this.createDate = createDate; this.userId = userId;
}
}
, но тип поиска может быть интерфейсом, который просто имеет некоторые из тех же свойств. Если вы хотите, чтобы у этого типа было имя, вы можете сделать это следующим образом:
// if you must name this type, you can do this:
interface SourceOfAddressLookup extends Pick<SourceOfAddressDto,
"sourceOfAddressCode" |
"sourceOfAddressDescription" |
"sourceOfAddressId" |
"sourceOfAddressLabel"
> { }
В общем, я бы использовал функцию типа pluck()
, чтобы взять существующий объект и создать новый, скопировав список свойств:
function pluck<T, K extends keyof T>(t: T, ...k: K[]) {
return k.reduce((a, k) => (a[k] = t[k], a), {} as Pick<T, K>)
}
И тогда ваша функция mapFromSourceOfAddressDto
может использовать ее следующим образом:
function mapFromSourceOfAddressDto(obj: SourceOfAddressDto): SourceOfAddressLookup {
return pluck(
obj,
"sourceOfAddressId",
"sourceOfAddressCode",
"sourceOfAddressDescription",
"sourceOfAddressLabel"
);
}
И мы можем убедиться, что она работает:
const dto = new SourceOfAddressDto(new Date(), "abc");
dto.sourceOfAddressCode = "cod";
dto.sourceOfAddressDescription = "descrip";
dto.sourceOfAddressLabel = "lab";
dto.sourceOfAddressId = 1;
const lookup = mapFromSourceOfAddressDto(dto);
console.log(JSON.stringify(lookup));
/* {
"sourceOfAddressId":1,
"sourceOfAddressCode":"cod",
"sourceOfAddressDescription":"descrip",
"sourceOfAddressLabel":"lab"
}
*/
Хорошо выглядит для меня. Надеюсь, что это поможет дать вам некоторое направление; удачи!
Детская площадка ссылка на код