繁体   English   中英

如何避免 Typescript 中的可选链接?

[英]How can I avoid optional chaining in Typescript?

我试图在 redux 中存储名为Targetfarms的 object 数据。我为Targetfarms分配了一个名为Farmstype的类型。

但是,当我在MainPage组件中使用带有TargetfarmsuseSelector并且我想使用targetfarm.aircon时,如果我不在Targetfarms中使用可选链接,则会发生此错误。

Targetfarms is possibly null,

如果我使用optional chaining,我可以正常获取Targetfarms数据,但我不想尽可能使用optional chaining。

我该如何修复我的代码?

这是我的代码:

export interface Farmstype {
    aircon: aircontype;
    children: Farmstype[];
    equips: euiptype[];
    latitude: number;
    longitude: number;
    modDate: string;
    name: string;
    placeId: number;
    placeInfo: placeInfotype;
    productCode: string;
    productCodeInfo: productCodeInfotypes;
    productLifeCycles: productLifeCyclestype[];
    roadNameAddress: string;
    stnIds: number;
    type: string;
}

interface InitialState {
    Targetfarms: Farmstype | null;
}

const initialState: InitialState = {
    Targetfarms: null,
};



const postSlice = createSlice({
    name: "post",
    initialState,
    reducers: {
        // targetLoadFarm
        targetFarm(state, action: PayloadAction<Farmstype>) {
            state.Targetfarms = action.payload;
        },
    }

主页

const MainPage = () => {
    const { Targetfarms} = useSelector((state: RootState) => state.post);

    console.log("Targetfarms:", Targetfarms?.placeId);    // Targetfarms is possibly null,

}

摆脱当前设置的可选链接的一个想法是静态键入世界的 state 并编写不同的组件。

不确定我是否正确构建了您的商店,但您明白了。

type RootState = {
    app: 'init' | 'running' // we model the state of the app
    post: {
       Targetfarms: Farmstype | null
    }
}

// We dispatch to the correct implementation depending on the state of the world
const MainPage = () =>
    useSelector({ app }: RootState) => app) === 'running'
        ? RunningPage()
        : InitPage();

const RunningPage = () => {
    const { Targetfarms } = useSelector((state: RunningState) => state.post);

    // OK
    const f = Targetfarms.placeId

}

const InitPage = () => {
    const { Targetfarms } = useSelector((state: InitState) => state.post);

    // @ts-expect-error: Targetfarms is possibly null
    const f = Targetfarms.placeId

}

有许多方法可以产生不同的状态。 这是一个选项。

// When the app is 'running' `post/Targetfarms` is unlocked
type RunningState = Unlock<RootState, ['post', 'Targetfarms']> & {
   state: 'running'
};

// Otherwise Targetfarms is still nullable
type InitState = RootState & {
   state: 'init'
};

type Unlock<State, Path extends PropertyKey[]> = unknown & {
    [K in keyof State]: Path['length'] extends 1
        ? K extends Path[0] ? NonNullable<State[K]> : State[K]
        : Unlock<
            State[K],
            Path extends [PropertyKey, ...infer U] ? U  & PropertyKey[] : never
        >
}

如果您的app状态很少,而 state 有很多可为 null 的部分,那么此解决方案可能会开始变得有趣。基本上,您可以在根目录中一次性决定应用程序在 state 中的位置,而不是多次在需要值的位置。

也许您正在尝试访问 object 的属性,该属性在初始化之前可能是 null 或未定义。 为避免此错误,您有以下几种选择:

在尝试访问其属性之前,您可以检查 object 是 null 还是未定义。 例如:

if (Targetfarms) {
  console.log(Targetfarms.placeId);
}

您可以使用 || 为 Targetfarms 设置默认值操作员。 例如:

const {Targetfarms} = useSelector((state: RootState) => state.post) || {};
console.log(Targetfarms.placeId);

这会将 Targetfarms 的默认值设置为空 object,这意味着您可以访问其属性而不会出现错误。

注意:我认为并且这只是我的意见,可选链接是避免 null 或未定义的好方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM