在使用 typescript/jsdoc 进行转换时,如何通过属性赋值处理类型转换?

问题描述 投票:0回答:2
type FromType = {
  // [...]
  value: string;
}

type ToType = Omit<FromType, 'value'> & {
  value: number;
}

然后

/**
 * @param {FromType[]} records
 * @returns {ToType[]} records
 */
function transform(records){
  return records.map((record) => {
    record.value = parseFloat(record.value);
    
    return record;
  });
}

抱怨因为

record.value
应该是一个字符串。解决方法是使用
Object.assign

/**
 * @param {FromType[]} records
 * @returns {ToType[]} records
 */
function transform(records){
  return records.map((record) => {
    return Object.assign(record, {
      value: parseFloat(record.value),
    });
  });
}

如何处理作业的类型转换?

假设:

  • 变异是安全的
  • 我不想定义一个不正确的输入属性具有
    string | number
    .
  • 出于性能原因,我不想制作新对象,即
    { ...item, value: 0 }
typescript jsdoc
2个回答
2
投票

抱歉,我不知道如何使用 JSDoc 对此进行注释,但是使用 TypeScript 自己的类型注释来执行该突变,您会短暂地对 TypeScript 撒谎以欺骗它允许它:

type FromType = {
    // [...]
    value: string;
};

type ToType = Omit<FromType, "value"> & {
    value: number;
};

type X = ToType["value"];

/**
 * @param   records The record to transform.
 * @returns Transformed records.
 */
function transform(records: FromType[]): ToType[] {
    return records.map((record) => {
        const result = record as any as ToType;     // A brief lie...
        result.value = parseFloat(record.value);    // ...which is now true
        return result;
    });
}

操场上的实例

如果你能避免突变,我会强烈鼓励它(那就是

return records.map((value, ...rest) => ({...rest, value: parseFloat(value)}));
),但如果你不能避免它,你就无法避免它。 :-)

因为你正在改变对象,除非你有一个非常不寻常的用例,否则没有理由创建一个新数组,不这样做也可能有助于解决你的性能问题:

/**
 * @param   records The record to transform.
 * @returns The **same** array, objects are mutated in place.
 */
function transform(records: FromType[]): ToType[] {
    for (let n = records.length - 1 ; n >= 0; --n) {
        const record = records[n];
        const result = record as any as ToType;     // A brief lie...
        result.value = parseFloat(record.value);    // ...which is now true
    }
    return records as any as ToType[];
}

游乐场链接

即使您确实需要创建一个新数组,鉴于此函数正在适当地发生变化,让调用者做的事情可能是有意义的(也许通过

slice
,这非常快)。


-2
投票

Object.assign
尽善尽美(打字除外)
https://tsplay.dev/N5Ab0N
(注意 ToType 被移除以查看推断的类型)

type FromType = {
    value: string;
};

function transform1(records: FromType[]) {
    return records.map((record) => {
        return override(record, 'value', parseFloat(record.value))
    });
}
type R1 = ReturnType<typeof transform1>
//   ^?
// type R1 = { value: number; }[]
function transform2(records: FromType[]) {
    return records.map((record) => {
        return assign(record, { value: parseFloat(record.value) })
    });
}
type R2 = ReturnType<typeof transform2>
//   ^?
// type R2 = { value: number; }[]

type Pure<T> = { [K in keyof T]: T[K] }
function override<O, K extends PropertyKey, V>(o: O, k: K, v: V): { [P in (keyof O) | K]: P extends K ? V : O[P & keyof O] } {
    (o as Record<K, V>)[k] = v;
    return o as any;
}
function assign<O extends object, V extends object>(o: O, v: V): { [P in keyof O | keyof V]: P extends keyof V ? V[P] : O[P & keyof O] } {
    return Object.assign(o, v) as any;
}
© www.soinside.com 2019 - 2024. All rights reserved.