【问题标题】:Argument of type '{ [key: string]: any; }' is not assignable to parameter of type 'any[]''{ [key: string]: any; 类型的参数}' 不可分配给“any[]”类型的参数
【发布时间】:2020-03-19 02:51:22
【问题描述】:

我正在尝试使用ngrx 做一个简单的口袋妖怪应用程序。我正在使用 lodash 库来做一个键值数组。我在填充 MatTableDataSource 所需的几乎所有步骤中都取得了成功,但我不知道如何为此提供正确的类型。所以我需要接收我的数据并用它填充我的dataSource.data,但我收到此错误:“类型'{ [key:string]:any;}'的参数不可分配给'any []'类型的参数。类型 '{ [key: string]: any; }' 缺少类型 'any[]' 中的以下属性:length、pop、push、concat 和另外 26 个”。因为这个,我的表没有渲染。如何为我的 MatTableDataSource 提供正确的类型或解决此问题?

问候

听到响应并将值设置为 MatTableDataSource 的我的 Observable 'pokemon.component.ts'

public readonly pokemonsSubscription = this.store.pipe(select(fromPokemons.pokemons)).subscribe(pokemons => {
    if (!pokemons || pokemons.length === 0) {
      return;
    }
    //the error is below
    this.dataSource.data = new MatTableDataSource(pokemons);

    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  });

这是我的口袋妖怪存储'pokemon.store.ts'

export const selectPokemonsState = (appState: AppState) => appState.Pokemons;

export const pokemons = createSelector(selectPokemonsState, (pokemonsState: PokemonsState) => pokemonsState.pokemons);
export const isLoading = createSelector(selectPokemonsState, (pokemonsState: PokemonsState) => pokemonsState.isLoading);
export const initial = createSelector(selectPokemonsState, (pokemonsState: PokemonsState) => pokemonsState.initial);
export const final = createSelector(selectPokemonsState, (pokemonsState: PokemonsState) => pokemonsState.final);

这些是我的动作'pokemons.actions.ts'

export enum Action {
    PokemonsLoad = '[Pokemons] Load',
    PokemonsLoadSuccess = '[Pokemons] Load Success',
    PokemonsLoadError = '[Pokemons] Load Error',
    PokemonLoadByQuantity = '[Pokemon] Load By Quantity',
    PokemonLoadByQuantitySuccess = '[Pokemon] Load By Quantity Success',
    PokemonLoadByQuantityError = '[Pokemon] Load By Quantity Error',
}

export const PokemonsLoad = createAction(Action.PokemonsLoad);
export const PokemonsLoadSuccess = createAction(Action.PokemonsLoadSuccess, props<{ payload: Array<any> }>());
export const PokemonsLoadError = createAction(Action.PokemonsLoadError, props<{ payload: any }>());
export const PokemonLoadByQuantity = createAction(Action.PokemonLoadByQuantity, props<{ payload: { initial: number, final: number }}>());
export const PokemonLoadByQuantitySuccess = createAction(Action.PokemonLoadByQuantitySuccess, props<{ payload: Array<any> }>());
export const PokemonLoadByQuantityError = createAction(Action.PokemonsLoadError, props<{ payload: any }>());

我的减速器'pokemons.reducer.ts'

export interface PokemonsState {
    pokemons: { [key: string]: any };
    isLoading: boolean;
    initial: number;
    final: number;
    quantityOfAllPokemons: number;
}

export const pokemonsInitialState: PokemonsState = {
    pokemons: {},
    isLoading: false,
    initial: 1,
    final: 24,
    quantityOfAllPokemons: undefined,
};

const pokemonsReducer = createReducer(
    pokemonsInitialState,
    on(pokemonsActions.PokemonsLoadSuccess, (state, { payload }) => (
        {
            ...state,
            pokemons: keyBy(PokemonNumber.pokemonNumber(payload), 'id'),
            isLoading: false,
            quantityOfAllPokemons: payload.length
        }
    )
    ),
    on(pokemonsActions.PokemonLoadByQuantitySuccess, (state, { payload }) => (
        {
            ...state,
            pokemons: keyBy( Object.values(state.pokemons).concat(payload), 'id'),
            isLoading: false,
            initial: PokemonNumber.nextSearch(state.final, state.quantityOfAllPokemons, 1),
            final: PokemonNumber.nextSearch(state.final, state.quantityOfAllPokemons, 12)
        }
    )
    ),
    on(pokemonsActions.PokemonsLoad, (state) => (
        {
            ...state,
            isLoading: true
        }
    )
    ),
    on(pokemonsActions.PokemonLoadByQuantity, (state) => (
        {
            ...state,
            isLoading: true
        }
    )
    ),
);

export function reducer(pokemonState: PokemonsState | undefined, action: Action) {
    return pokemonsReducer(pokemonState, action);
}

export const pokemonsFeatureKey = 'Pokemons';

效果'pokemons.effects.ts'

@Injectable()
export class PokemonsEffects {

    loadAllPokemons$ = createEffect(() => this.actions$.pipe(
        ofType(Action.PokemonsLoad),
        switchMap((payload) => {
            return this.pokemonsService.getAllPokemons()
                .pipe(
                    map(pokemons => (PokemonsLoadSuccess({ payload: pokemons }))),
                    catchError((msg) => of(PokemonsLoadError({ payload: msg }))),
                );
        })
    )
    );

    loadPokemonByQuantity$ = createEffect(() => this.actions$.pipe(
        ofType(Action.PokemonLoadByQuantity),
        switchMap((payload) => {
            return this.pokemonsService.loadPokemonByQuantity(payload['payload']['initial'], payload['payload']['final'])
                .pipe(
                    map(pokemons => (PokemonLoadByQuantitySuccess({ payload: pokemons }))),
                    catchError((msg) => of(PokemonLoadByQuantityError({ payload: msg }))),
                );
        })
    )
    );

    success$ = createEffect(() => this.actions$.pipe(
        ofType<{ type: string, payload: any }>(
            // Action.PokemonsLoadSuccess,
            // Action.PokemonLoadByQuantitySuccess,
        ),
        tap(({ type, payload }) => { window.alert('Sucesso'); })
    ), { dispatch: false });

    error$ = createEffect(() => this.actions$.pipe(
        ofType<{ type: string, payload: string }>(
            Action.PokemonsLoadError,
            Action.PokemonLoadByQuantityError,
        ),
        tap(({ type, payload }) => { window.alert('Erro'); }),
    ), { dispatch: false });

    constructor(private actions$: Actions, private pokemonsService: PokemonsService) { }
}

我关于这个错误的堆栈闪电在下面

stackblitz

【问题讨论】:

  • 我们在 stackblitz 中看不到您的代码。使用您的 stackblitz 编辑器链接更改它
  • 对不起,伙计。但是现在我已经更改了上面的链接。

标签: javascript angular typescript angular-material lodash


【解决方案1】:

错误表明您正在尝试将对象分配给数组类型的属性。在下面的行中:

this.dataSource.data = new MatTableDataSource(pokemons);

MatTableDataSource() 需要一个数组,但似乎pockemons 不是一个正确的对象数组。例如,您可以通过 console.log(Array.isArray(pockemons)); 来验证这一点。

一旦您确认 pockemons 不是对象数组,您就可以将该对象放入对象数组中(或发布单独的问题)。

您还应该将上面的行更改为(删除.data):

this.dataSource = new MatTableDataSource(pokemons);

更新

在仔细检查您的 stackblitz 后,似乎当从商店中检索到 pokemons 时,即使它是一系列对象,它也不是作为对象数组进入的。

【讨论】:

  • 我知道这是一个对象,但我想在我的表中呈现这个对象。有没有办法做到这一点?或者一种将这个对象解析为数组的方法?
【解决方案2】:

我正在使用 lodash 库来做一个键值数组

你根本没有创建一个数组,它实际上是一个对象的对象,示例:

{
    "1": {
        "name": "bulbasaur",
        "url": "https://pokeapi.co/api/v2/pokemon/1/",
        "id": 1
    },
    "2": {
        "name": "ivysaur",
        "url": "https://pokeapi.co/api/v2/pokemon/2/",
        "id": 2
    }
}

我不明白为什么您实际上需要这样做,并且根据您的表的设置方式,它需要一个类似于您从 API 获得的数组。无论如何,您正在使用 pokemonNumber 为您的口袋妖怪创建 id,您将使用它来获取 PokemonLoadByQuantitySuccess 中每个口袋妖怪的个人数据。

所以我会这样做:

on(pokemonsActions.PokemonsLoadSuccess, (state, { payload }) => (
  {
    ...state,
    pokemons: PokemonNumber.pokemonNumber(payload), // <<<<<<<<<< this instead
    // pokemons: keyBy(PokemonNumber.pokemonNumber(payload), 'id'),
    isLoading: false,
    quantityOfAllPokemons: payload.length
  }
)

好的,那么在为每个 pokemon 获取数据时,您使用的是concat,这不适合这里,因为您只是连接数组。您想要的是根据 id 将数据附加到特定的口袋妖怪。这可能会做得更干净,但至少这是可行的:

on(pokemonsActions.PokemonLoadByQuantitySuccess, (state, { payload }) => (
  {
    ...state,
    // pokemons: keyBy( Object.values(state.pokemons).concat(payload), 'id'),
    // below instead!!
    pokemons: state.pokemons.map((p, i) => { return {... p, ...payload.find(i => i.id === p.id)}}),
    isLoading: false,
    initial: PokemonNumber.nextSearch(state.final, state.quantityOfAllPokemons, 1),
    final: PokemonNumber.nextSearch(state.final, state.quantityOfAllPokemons, 12)
  }
)

最后,就像在其他答案中删除 data 来自:

this.dataSource = new MatTableDataSource(pokemons);

这似乎行得通。

你的分叉STACKBLITZ

您可能想要调整商店中的 loading 属性,目前在获取宠物小精灵的所有个人数据时,图像出现延迟(至少对我而言)。

【讨论】:

    猜你喜欢
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 2019-09-06
    • 2019-01-09
    • 2017-01-30
    • 2021-12-03
    • 2021-06-10
    相关资源
    最近更新 更多