Отображенная запись вызывает тип any, когда рекурсивно

Давайте перепишем ваш код следующим образом:

x = 1
y = [x]
z = y * 4

myList = [z] * 3

После этого запустите следующий код, чтобы сделать все более понятным. Что делает код, в основном печатает id s полученных объектов, которые

Вернуть «идентификатор» объекта

и поможет нам идентифицировать их и проанализировать, что происходит:

print("myList:")
for i, subList in enumerate(myList):
    print("\t[{}]: {}".format(i, id(subList)))
    for j, elem in enumerate(subList):
        print("\t\t[{}]: {}".format(j, id(elem)))

И вы получите следующий результат:

x: 1
y: [1]
z: [1, 1, 1, 1]
myList:
    [0]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [1]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [2]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528

Итак, теперь давайте шаг за шагом. У вас есть x, который является 1, и единственным списком элементов y, содержащим x. Ваш первый шаг - y * 4, который даст вам новый список z, который в основном [x, x, x, x], т. Е. Создает новый список, который будет содержать 4 элемента, которые являются ссылками на исходный объект x. Чистый шаг очень похож. В основном вы делаете z * 3, который является [[x, x, x, x]] * 3 и возвращает [[x, x, x, x], [x, x, x, x], [x, x, x, x]] по той же причине, что и для первого шага.

0
задан samdd 24 March 2019 в 03:56
поделиться

1 ответ

Хм, вы носите здесь множество взаимно ссылочных универсальных типов, и без использования и примеров использования, я признаю, я почти не представляю, что здесь происходит, и действительно ли это лучший способ представить вашу структуру данных , Я предполагаю, что вы, вероятно, могли бы обойтись без единственного параметра типа, подобного этому:

class Obj<T>
{
    constructor(public fields: { [K in keyof T]: Obj<T[K]> }) {
    }
    public data!: T
}

Но даже если вы сделаете это, у вас все равно будет та же проблема, которая обнаружится, если вы включите более строгий режим [119 ] опции компилятора , такие как --noImplicitAny или --strict. Затем вы увидите, что ваше определение recursive дает вам следующие ошибки:

'recursive' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

и

[ 117]

Это предполагаемое поведение , когда компилятор не может вывести тип, потому что он определенным образом зависит от самого себя. Предлагаемый способ справиться с этим обычно состоит в том, чтобы дать явную аннотацию типа одной из частей, чтобы разорвать круглость. Это раздражает, потому что вынуждает вас избыточно записывать наборы к вещам, которые были ранее выведены компилятором, но я не знаю, есть ли хороший способ избежать этого.

Вот один из способов сделать это с типами, какими они у вас являются:

// explicit type
interface RecursiveObj extends Obj<
    DataType<
        { readonly query: RecursiveObj; test: Obj<{}, {}>; }
    >, { readonly query: RecursiveObj; test: Obj<{}, {}>; }> {
}

const recursive = new Obj({
    // explicitly annotated return type
    get query(): RecursiveObj {
        return recursive
    },
    test: new Obj({})
}); // okay now

И вот как я это сделаю с упрощенным Obj<T> типом I, перечисленным выше:

[112 ]

Хорошо, надеюсь, это поможет. Удачи!

0
ответ дан jcalz 24 March 2019 в 03:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: