可选链与非空操作符

? : 可选链操作符,用于访问对象属性时,如果该属性不存在,则返回 undefined或null,而不是抛出错误导致页面报错。

! : 非空断言操作符,告诉编译器某个表达式不会是 null或undefined,从而避免类型检查错误。

TypeScript 复制代码
<template>
  <div class="option-sel-and-have-view">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>?与!的使用</span>
        </div>
      </template>
      <div>
        <el-text class="intro">
        ? ------------ 可选链操作符,用于访问对象属性时,如果该属性不存在,则返回 undefined或null,而不是抛出错误导致页面报错。
        </el-text>
      </div>
      <div>
        <el-text class="intro">
        ! ------------ 非空断言操作符,告诉编译器某个表达式不会是 null或undefined,从而避免类型检查错误。
        </el-text>
      </div>
      <div class="btnbox">
        <el-button type="primary" @click="clickedOptionSelect">
          点击触发 ? --------- 可选链操作符示例  
        </el-button>
        <el-button type="success" @click="clickedNonNullAssertion">
          点击触发 ! --------- 非空断言操作符示例
        </el-button>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
const clickedOptionSelect = () => {
    interface User {
        name: string;
        address?: {
        street: string;
        city: string;
        };
    }
    
    const user: User = {
        name: "Alice",
    };
    

    /* 
        使用可选链操作符访问地址属性,在一个对象属性深度层级较多时非常有用,
        比如const width = user.address?.street?.width, 
        然后这样就可以了 if(width) { ... }
    */
    const street = user.address?.street;
    if (street) {
        alert(`街道名称: ${street}`);
    } else {
        alert("地址信息不可用");
    }

    // 如果不用可选链操作符,会是下面这样写,当属性深度层级为多级时不使用可选链操作符代码会嵌套多个if,不易阅读
    if(user.address && user.address.street) {
        alert(`街道名称: ${user.address.street}`);
    } else {
        alert("地址信息不可用");
    }
}

const clickedNonNullAssertion = () => {
    interface User {
        name: string;
        address: {
            street: string;
            city: string;
        };
    }

    const user: User = {
        name: "Alice",
        address: {
            street: "123 Main St",
            city: "New York"
        }
    };

    // 使用非空断言操作符访问地址属性
    // 告诉编译器 user.address 不会是 null 或 undefined,如果不这样写eslint会有错误的提示,或者报错
    // 当属性层级比较多时,这样用也是非常简洁
    const street = user.address!.street;
    alert(`街道名称: ${street}`);
}
</script>

<style lang="scss" scoped>
.option-sel-and-have-view {
  width: 100%;
  height: 100%;
  overflow: auto;
  box-sizing: border-box;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 18px;
  font-weight: bold;
}

.el-alert {
  margin-top: 20px;
}

.intro {
  margin-top: 20px;
  font-size: 14px;
  color: rgb(84, 144, 229);
}

.btnbox {
  margin-top: 20px;
  display: flex;
  gap: 10px;
}

</style>
相关推荐
一点一木13 小时前
深度体验TRAE SOLO移动端7天:作为独立开发者,我把工作流揣进了兜里
前端·人工智能·trae
天外飞雨道沧桑13 小时前
TypeScript 中 omit 和 record 用法
前端·javascript·typescript
Lee川14 小时前
mini-cursor 揭秘:从 Tool 定义到 Agent 循环的完整实现
前端·人工智能·后端
canonical_entropy14 小时前
从 Spec-Driven Development 到 Attractor-Guided Engineering
前端·aigc·ai编程
研☆香14 小时前
聊聊前端页面的三种长度单位
前端
给钱,谢谢!15 小时前
React + PixiJS 实现果园成长页:从状态机到浇水动画
前端·react.js·前端框架
暗冰ཏོ16 小时前
VUE面试题大全
前端·javascript·vue.js·面试
次元工程师!16 小时前
LangFlow开发(三)—Bundles组件架构设计(3W+字详细讲解)
java·前端·python·低代码·langflow
Bug-制造者17 小时前
现代Web应用全栈开发:从架构设计到部署落地实战
前端
青春喂了后端17 小时前
IntelliGit 前端状态层重构:把一个全局 Store 拆成清晰的状态边界
前端·重构·状态模式