Клонирование объекта в Typescript, миграция из потока - PullRequest
0 голосов
/ 27 сентября 2018

По сути, мне нужна функция, которая клонирует (т.е. глубоко копирует) объекты, которые имеют некоторые общие свойства.«Общее свойство» - это, по сути, просто тег с именем op для операции.Итак, ранее у меня был какой-то код, набранный с использованием Flow:

export function cloneExpr<E: Expr>(exp: E): E {
    if (exp.op === POINT) {
        return ((expr.makePoint(exp.p, exp.x, exp.y):any):E);
    } ... etc
}

, где Expr - это объединение множества таких вещей, как Point, Line и т. Д., Каждый из которых имеет этот opполе.Кастинг несколько уродливый, но по крайней мере это работает;т.е. если я cloneExpr объект набрал Point, возвращаемый объект набрал Point без необходимости предоставления дополнительной информации о наборе.

Теперь я хотел бы перейти на Typescript, но у меня естькуча проблем.Тяжелое литье return ((exp as any) as Point) работает в вакууме, но мой охранник типов продолжает терять информацию, поэтому, например, я не могу получить поле x из Точки exp, не провалив проверку ввода.Чтобы заставить typeguard работать, я пробовал много вариантов типов функций, таких как:

function cloneExpr<T extends Expr>(exp: T): T

, где Expr - это что-то вроде Point | Line.

function cloneExpr<T extends IsExpr>(exp: T): T

где IsExpr - это интерфейс, который я определил только с полем op.

function cloneExpr(exp: Expr): Expr

, который я пробовал, но ясно, что я никогда не верну правильный тип ввода.

Так что либо я не получаю typeguard, либо тип возвращаемого значения не тот конкретный тип, который я ввел.Я также попытался переопределить объекты, используя интерфейсы, а затем предоставил определяемую пользователем защиту типа и что-то еще, но безрезультатно.

Как правильно сделать это в Typescript?Спасибо за тонну.

1 Ответ

0 голосов
/ 27 сентября 2018

Неспособность сузить exp с E до Point (или что-то в этом роде) при тестировании exp.op === POINT будет устранена этим предложением .Между тем, вы можете достичь того же уровня безопасности типов, который был у Flow, скопировав аргумент в локальную переменную типа Expr:

export function cloneExpr<E extends Expr>(exp: E): E {
    const exp1: Expr = exp;
    if (exp1.op === POINT) {
        return expr.makePoint(exp1.p, exp1.x, exp1.y) as any as E;
    }
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...