gpt4 book ai didi

typescript - 在 TypeScript 中,可选参数和未定义参数之间是否有区别?

转载 作者:行者123 更新时间:2023-12-04 12:13:21 25 4
gpt4 key购买 nike

我想知道这两段代码之间是否有区别:

function sayHello(name?: string) {
if (name) { return 'Hello ' + name; }
return 'Hello!';
}
function sayHello(name: string | undefined) {
if (name) { return 'Hello ' + name; }
return 'Hello!';
}
(我知道我不能在“名称”之后添加第二个不是可选的参数,因为它必须是最后一个或最后一个)
我今天早些时候在考虑这个问题,我觉得对我来说主要的区别首先是你所说的函​​数的使用者。
第一个更暗示可选性,比如“你不需要把这个传给我,但如果你愿意,你可以”
第二个说“传递给我一个字符串,我不在乎它是否未定义,我可以处理”。
类似的事情也可以出现在接口(interface)和类型中。
interface Foo {
thing?: string;
}
对比
interface Foo {
thing: string | undefined;
}
我在正确的轨道上吗?还有什么我应该知道的吗?

最佳答案

你走在正确的轨道上,而且几乎是正确的。

在接下来的内容中,我将假设您使用的是 --strict或者至少是 --strictNullChecks 编译器选项,以便 undefinednull并不总是隐式允许:

let oops: string = undefined; // error! 
// Type 'undefined' is not assignable to type 'string'

在 TypeScript 中,用 ? 标记为可选的函数/方法参数或对象类型的字段。修饰符意味着它可能会丢失:
function opt(x?: string) { }

interface Opt {
x?: string;
}

const optObj: Opt = {}; // okay
opt(); // okay
但也允许存在此类可选参数/字段,但 undefined :
const optObj2: Opt = { x: undefined } // okay
opt(undefined); // okay
实际上,如果您使用 IntelliSense 检查此类可选参数/字段的类型,您会看到编译器自动添加 undefined作为一种可能性:
function opt(x?: string) { }
// function opt(x?: string | undefined): void

interface Opt {
x?: string;
}
type AlsoOpt = Pick<Opt, "x">;
/* type AlsoOpt = {
x?: string | undefined;
} */
从函数的实现者或对象类型的使用者的角度来看,可选元素可以被视为它始终存在,但可能 undefined :
function opt(x?: string) {
// (parameter) x: string | undefined
console.log(typeof x !== "undefined" ? x.toUpperCase() : "undefined");
}

function takeOpt(v: Opt) {
const x = v.x;
// const x: string | undefined
console.log(typeof x !== "undefined" ? x.toUpperCase() : "undefined");
}

将此与包含 | undefined 的必填(非可选)字段或参数进行比较和对比。 :
function req(x: string | undefined) { }

interface Req {
x: string | undefined
}
与可选版本一样,必需的版本是 | undefined接受显式 undefined .但与可选版本不同的是,不能在完全缺少值的情况下调用或创建必需的版本:
req(); // error, Expected 1 arguments, but got 0!
req(undefined); // okay
const reqObj: Req = {}; // error, property x is missing!
const reqObj2: Req = { x: undefined } // okay
而且,与可选版本一样,函数的实现者或对象类型的使用者将看到可选的东西确实存在,但可能 undefined :
function req(x: string | undefined) {
// (parameter) x: string | undefined
console.log(typeof x !== "undefined" ? x.toUpperCase() : "undefined");
}

function takeReq(v: Req) {
const x = v.x;
// const x: string | undefined
console.log(typeof x !== "undefined" ? x.toUpperCase() : "undefined");
}

其他注意事项:

还有 optional elements in tuple types以相同的方式工作。它们类似于可选对象字段,但它们与参数具有相同的限制:如果任何元组元素是可选的,则所有后续元素也必须是可选的:
type OptTuple = [string, number?];
const oT: OptTuple = ["a"]; // okay
const oT2: OptTuple = ["a", undefined]; // okay

type ReqTuple = [string, number | undefined];
const rT: ReqTuple = ["a"]; // error! Source has 1 element(s) but target requires 2
const rT2: ReqTuple = ["a", undefined]; // okay

对于函数参数,有时也可以使用类型 void表示“失踪”,因此 | void表示“可选”,在 microsoft/TypeScript#27522 中实现.所以 x?: stringx: string | void处理方式类似:
function orVoid(x: string | void) {
console.log((typeof x !== "undefined" ? x.toUpperCase() : "undefined"));
}
orVoid(); // okay
对象字段还不是这种情况。已在 microsoft/TypeScript#40823 中实现,但尚未将其纳入语言(我不确定它是否会这样做):
interface OrVoid {
x: string | void;
}
const o: OrVoid = {} // error! x is missing

最后,我会告诉你 microsoft/TypeScript#13195 ,一个讨论 TypeScript 中“missing”和“present but undefined”之间有趣的历史关系的问题。有时它们被同等对待,有时它们被区别对待。
人们想要更多区别的一个主要地方是,当某些东西是可选的时,开发人员并不总是对显式传入 undefined 的可能性感到高兴。 .也就是说,人们想说的是 interface Opt {x?: string}应该意味着 x要么是 string ,或者完全丢失。他们认为如果你有一个值 o类型 Obj ,然后 o.x === undefined应该只在 "x" in o 时发生是 false .
但这不是 TypeScript 中默认发生的情况。在大多数编译器配置中, o.x === undefined不会让您知道该属性(property)是否存在-但是- undefined或失踪。等等 "x" in o并不能最终告诉您是否 o.xstringundefined .
有一个新的 --exactOptionalPropertyTypes compiler flag计划与 TypeScript 4.4 一起发布,启用后将不会添加 undefined到可选属性的域,等等 o.x === undefined意味着 x属性(property)不见了。但是,默认情况下不会启用此编译器选项,它仅适用于属性而不适用于函数参数。
无论如何,我建议避免丢失和 undefined 之间的差异的情况。事项。

Playground link to code

关于typescript - 在 TypeScript 中,可选参数和未定义参数之间是否有区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65986108/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com