0

我有一个简单的 MobX 商店:

import { observable, action, makeObservable } from "mobx"
import { BoxShadow, ShadowValues } from "./types"
import { boxShadow } from "./constants"

interface IStore {
    shadow: BoxShadow
}

export class Store implements IStore {
    shadow: BoxShadow = {
        selected: "DEFAULT",
        list: boxShadow,
    }
    constructor() {
        makeObservable(this, {
            shadow: observable,
            updateShadow: action.bound,
        })
    }

    updateShadow(selected: ShadowValues) {
        this.shadow.selected = selected
    }
}

export const store = new Store()

BoxShadow&ShadowValues类型包括:

type Point = {
    x: number
    y: number
}

export type ShadowValues =
    | "none"
    | "sm"
    | "DEFAULT"
    | "md"
    | "lg"
    | "xl"
    | "2xl"
    | "3xl"

export type Shadow = {
    offset: Point
    blur: number
    shadow: number
    color: string
}

export type ShadowList = Record<ShadowValues, Shadow[] | Shadow>

export type BoxShadow = {
    selected: ShadowValues
    list: ShadowList
}

我正在使用 HTML 选择和更新boxShadow值:

import * as React from "react"
import { toJS } from "mobx"
import { observer } from "mobx-react"

import { useStore } from "./context"
import { Select } from "./Select"
import { shadows } from "./constants"

import { ShadowValues } from "./types"

export default observer(function App() {
    const { shadow, updateShadow } = useStore()

    console.log(toJS(shadow.list[shadow.selected])[0]["offset"])
    console.log(shadow.list[shadow.selected].offset)

    return (
        <div className="w-full flex flex-col items-center">
            <h1 className="text-4xl">Access MobX Proxy</h1>
            <Select
                className="flex-1 w-56"
                label="Box Shadow"
                checkmark={true}
                options={shadows}
                selectedOption={
                    shadows.filter(({ value }) => value === shadow.selected)[0]
                }
                onChange={(selectedOption) => {
                    const selected = selectedOption.value as ShadowValues
                    updateShadow(selected)
                }}
            />
        </div>
    )
})

但是,我无法访问selectedShadow.colorselectedShadow.offset没有 TypeScript 对我大喊大叫。

这些boxShadow值由一个对象或对象数组组成,例如:

export const boxShadow = {
    none: {
        offset: { x: 0, y: 0 },
        blur: 0,
        shadow: 0,
        color: "rgba(0, 0, 0, 0)",
    },
    sm: {
        offset: { x: 0, y: 1 },
        blur: 2,
        shadow: 0,
        color: "rgba(0, 0, 0, 0.05)",
    },
    DEFAULT: [
        {
            offset: { x: 0, y: 1 },
            blur: 3,
            shadow: 0,
            color: "rgba(0, 0, 0, 0.1)",
        },
        {
            offset: { x: 0, y: 1 },
            blur: 2,
            shadow: 0,
            color: "rgba(0, 0, 0, 0.06)",
        },
    ],
    md: [
        {
            offset: { x: 0, y: 4 },
            blur: 6,
            shadow: -1,
            color: "rgba(0, 0, 0, 0.1)",
        },
        {
            offset: { x: 0, y: 2 },
            blur: 4,
            shadow: -1,
            color: "rgba(0, 0, 0, 0.06)",
        },
    ],
    lg: [
        {
            offset: { x: 0, y: 10 },
            blur: 15,
            shadow: -3,
            color: "rgba(0, 0, 0, 0.1)",
        },
        {
            offset: { x: 0, y: 4 },
            blur: 6,
            shadow: -2,
            color: "rgba(0, 0, 0, 0.05)",
        },
    ],
    xl: [
        {
            offset: { x: 0, y: 20 },
            blur: 25,
            shadow: -5,
            color: "rgba(0, 0, 0, 0.1)",
        },
        {
            offset: { x: 0, y: 10 },
            blur: 10,
            shadow: -5,
            color: "rgba(0, 0, 0, 0.04)",
        },
    ],
    "2xl": {
        offset: { x: 0, y: 25 },
        blur: 50,
        shadow: -12,
        color: "rgba(0, 0, 0, 0.25)",
    },
    "3xl": {
        offset: { x: 0, y: 35 },
        blur: 60,
        shadow: -15,
        color: "rgba(0, 0, 0, 0.3)",
    },
}

我正在尝试使用它来访问它,toJS但仍然无法访问嵌套属性。但是,如果我这样做,该.toJS方法显示得非常好console.log

import * as React from "react"
import { toJS } from "mobx"
import { observer } from "mobx-react"

import { useStore } from "./context"
import { Select } from "./Select"
import { shadows } from "./constants"

import { ShadowValues } from "./types"

export default observer(function App() {
    const { shadow, updateShadow } = useStore()

    console.log(toJS(shadow.list[shadow.selected])[0]["offset"])
    console.log(shadow.list[shadow.selected].offset)

    return (
        <div className="w-full flex flex-col items-center">
            <h1 className="text-4xl">Access MobX Proxy</h1>
            <Select
                className="flex-1 w-56"
                label="Box Shadow"
                checkmark={true}
                options={shadows}
                selectedOption={
                    shadows.filter(({ value }) => value === shadow.selected)[0]
                }
                onChange={(selectedOption) => {
                    const selected = selectedOption.value as ShadowValues
                    updateShadow(selected)
                }}
            />
        </div>
    )
})

看看console.log上面的。我想以某种方式访问​​这些值。

如果我这样做shadow.list[shadow.selected][0].color,我会得到:

TS7053:元素隐式具有“任何”类型,因为“0”类型的表达式不能用于索引类型“字符串 |” 阴影[] | 阴影'。类型“字符串”上不存在属性“0”| 阴影[] | 阴影'。

如果我这样做shadow.list[shadow.selected].color,我会得到:

TS2339:“字符串”类型不存在属性“颜色”| 阴影[] | 阴影'。“字符串”类型不存在属性“颜色”。

这是正确的,但我不知道如何解决它:(

我制作了一个最小的 Codesandbox来查看演示。请注意,它有时console.log在 Codesandbox 上,但不在本地,但它也会在 Codesandbox 上给出 TS 错误。

我该如何解决这个问题?我也想访问对象值sm.offset加上对象数组DEFAULT[0].offset& DEFAULT[1].offset:)

4

1 回答 1

0

由于我的类型为Shadow | Shadow[],因此当我必须访问它时,我必须添加一个保护来缩小类型。所以我做了以下工作来使它工作:

if (Array.isArray(selected)) {
    console.log(selected[0].offset);
} else {
    console.log(selected.offset);
}

我试过typeof selected了,它一直在给我object,我忘记了 JS 认为一切都是如此,object所以从未尝试过上述的东西 :)

于 2021-02-07T07:12:44.720 回答