至少知道TypeScript是如何工作的,每个人都可以回答:“是的。TypeScript只是将代码转到JavaScript上,但没有添加任何额外的行为,包括在执行过程中的类型检查。”例如,
function example(parameter: string): void {
console.log(parameter.charAt(1));
}将转到:
"use strict";
function example(parameter) {
console.log(parameter.charAt(1));
}如果JavaScript用户将调用example(3),则将引发错误Uncaught TypeError: parameter.charAt is not a function。
好吧,如果我明白我为什么要问这个问题?因为我将花费数十个小时来改进我的库(@yamato-daiwa/es-分机)),但更重要的是,将库大小增加多倍。不是夸大其词。例如,对于1.6.x版本,addElementsToArray函数非常简单,没有依赖关系:
export default function addElementsToArray<ArrayElement>(
namedParameters:
{
targetArray: Array<ArrayElement>;
newElements: Array<ArrayElement>;
mutably: boolean;
} &
(
{ toStart: true; } |
{ toEnd: true; } |
{ toPosition__numerationFrom0: number; } |
{ toPosition__numerationFrom1: number; }
)
): Array<ArrayElement> {
const workpiece: Array<ArrayElement> = namedParameters.mutably ?
namedParameters.targetArray : [ ...namedParameters.targetArray ];
if ("toStart" in namedParameters) {
workpiece.unshift(...namedParameters.newElements);
return workpiece;
}
if ("toEnd" in namedParameters) {
workpiece.push(...namedParameters.newElements);
return workpiece;
}
const positionOfFirstNewElement__numerationFrom0: number = "toPosition__numerationFrom0" in namedParameters ?
namedParameters.toPosition__numerationFrom0 : namedParameters.toPosition__numerationFrom1 - 1;
workpiece.splice(positionOfFirstNewElement__numerationFrom0, 0, ...namedParameters.newElements);
return workpiece;
}一旦我用类型检查改进了它,它就变成了:
import Logger from "../Logging/Logger";
import InvalidParameterValueError from "../Errors/InvalidParameterValue/InvalidParameterValueError";
import IncompatiblePropertiesInObjectTypeParameterError from
"../Errors/IncompatiblePropertiesInObjectTypeParameter/IncompatiblePropertiesInObjectTypeParameterError";
import stringifyAndFormatArbitraryValue from "../Strings/stringifyAndFormatArbitraryValue";
import isArbitraryObject from "../TypeGuards/Objects/isArbitraryObject";
import isNotUndefined from "../TypeGuards/Nullables/isNotUndefined";
import isNonNegativeInteger from "../TypeGuards/Numbers/isNonNegativeInteger";
import isNaturalNumber from "../TypeGuards/Numbers/isNaturalNumber";
export default function addElementsToArray<ArrayElement>(
namedParameters:
Readonly<
(
{
mutably: true;
targetArray: Array<ArrayElement>;
} |
{
mutably: false;
targetArray: ReadonlyArray<ArrayElement>;
}
) &
{
newElements: ReadonlyArray<ArrayElement>;
toStart?: true;
toEnd?: true;
toPosition__numerationFrom0?: number;
toPosition__numerationFrom1?: number;
}
>
): Array<ArrayElement> {
if (!isArbitraryObject(namedParameters)) {
Logger.throwErrorAndLog({
errorInstance: new InvalidParameterValueError({
parameterNumber: 1,
parameterName: "namedParameters",
messageSpecificPart: "The first and only parameter of 'addElementsToArray' must be of the object type."
}),
title: InvalidParameterValueError.localization.defaultTitle,
occurrenceLocation: "addElementsToArray(namedParameters)"
});
}
if (!Array.isArray(namedParameters.targetArray)) {
Logger.throwErrorAndLog({
errorInstance: new InvalidParameterValueError({
parameterName: "namedParameters",
parameterNumber: 1,
messageSpecificPart: "The 'targetArray' is not the valid array and has value:\n" +
`${ stringifyAndFormatArbitraryValue(namedParameters.targetArray) }`
}),
title: InvalidParameterValueError.localization.defaultTitle,
occurrenceLocation: "addElementsToArray(namedParameters)"
});
}
const alternativelyRequestOptions: Array<true | number> = [
namedParameters.toStart,
namedParameters.toEnd,
namedParameters.toPosition__numerationFrom0,
namedParameters.toPosition__numerationFrom1
].filter(isNotUndefined);
if (alternativelyRequestOptions.length > 1) {
Logger.logError({
errorType: IncompatiblePropertiesInObjectTypeParameterError.NAME,
title: IncompatiblePropertiesInObjectTypeParameterError.localization.defaultTitle,
description: "Exactly one of 'toStart', 'toEnd', 'toPosition__numerationFrom0', 'toPosition__numerationFrom1' " +
"must be specified while actually multiple of them has been. No elements will be added to target array.",
occurrenceLocation: "addElementsToArray(namedParameters)"
});
return namedParameters.targetArray;
}
const workpiece: Array<ArrayElement> = namedParameters.mutably ?
namedParameters.targetArray : [ ...namedParameters.targetArray ];
if (namedParameters.toStart === true) {
workpiece.unshift(...namedParameters.newElements);
return workpiece;
}
if (namedParameters.toEnd === true) {
workpiece.push(...namedParameters.newElements);
return workpiece;
}
let positionOfFirstNewElement__numerationFrom0: number;
if (isNonNegativeInteger(namedParameters.toPosition__numerationFrom0)) {
positionOfFirstNewElement__numerationFrom0 = namedParameters.toPosition__numerationFrom0;
} else if (isNaturalNumber(namedParameters.toPosition__numerationFrom1)) {
positionOfFirstNewElement__numerationFrom0 = namedParameters.toPosition__numerationFrom1 - 1;
} else {
Logger.logError({
errorType: InvalidParameterValueError.NAME,
title: InvalidParameterValueError.localization.defaultTitle,
description: alternativelyRequestOptions.length === 0 ?
"None one of 'toStart', 'toEnd', 'toPosition__numerationFrom0', 'toPosition__numerationFrom1' has been specified." :
(
"The specified value of 'toStart', 'toEnd', 'toPosition__numerationFrom0' or 'toPosition__numerationFrom1' has " +
"invalid type, value or numbers set."
) +
"No elements will be added to target array.",
occurrenceLocation: "addElementsToArray(namedParameters)"
});
return namedParameters.targetArray;
}
workpiece.splice(positionOfFirstNewElement__numerationFrom0, 0, ...namedParameters.newElements);
return workpiece;
}在这种情况下,验证占用了大约一半的行,并且出现了许多依赖项。有时,验证可能超过90%的功能行。库的可分发性将因多种类型而变得更重,这对于前端应用程序来说至关重要,因为在前端应用程序中,每千字节都是计数的。
上面的检查还不够细致!此外,我们可以:
toStart、toEnd、toPosition__numerationFrom0、toPosition__numerationFrom1)超过1时,请检查其中哪些参数确实已被传递,并记录它们的名称。toStart或toEnd具有false值,或者toPosition__numerationFrom0或toPosition__numerationFrom1为负数或小数),则分别对其进行记录。潜在的虚假问题
简而言之,我可以由非类型记录用户报告无效参数类型引起的错误,但是如果TypeScript编写了相同的代码,TypeScript就会发出错误。最终可以清楚地看出,这一问题是由于与JavaScript的结合而不是TypeScript的无效参数类型所造成的,调查、交谈等都会浪费时间,而且可能是大量的此类问题实际上就是无效的TypeScript。
赏金之际的最新情况
这个问题已经得到了回答,但是由于参数验证,我的库的大小在未来可能会增加很多倍,这让我感到困扰。为了解决这个问题,我需要有人告诉我:“你做的是对的,继续做下去!如果由于参数验证,分布者的规模增加了多次,对于前端应用程序来说,这一点都不重要。”或者“如果是因为参数的验证,那么助手库的大小就不好了。您应该跳过参数验证以保持库的苗条”。由高级/硕士网页开发人员提供。
发布于 2022-08-19 00:45:17
在系统面向客户的边缘进行验证是一种很好的实践。
在开始的时候,所有的清喉代码都可以被看作是一件好事,使这些功能的主体更加简单和自信地编写。
当然,您还可以通过查找或构建断言库来缩小代码。
发布于 2022-10-31 21:20:03
你似乎把两个不同的问题混为一谈。一方面,您可以输入用户正在访问的接口(例如函数签名),这允许TypeScript客户端验证函数调用是用适当的值进行的,并且是模块很好地处理TypeScript项目所必需的。另一方面,您需要对接口进行验证,对每个输入进行编程检查,以确保其具有适当的类型和值。
通常是TypeScript的最大优点之一,就是这些编程检查是不必要的。
我要提醒您不要验证每一个输入,就像您在示例中所做的那样。这并不能保证你总是会阻止所有不允许的值,而且在“每千字节计数”的情况下,你也想避免做大量的检查,而这些检查在任何地方都可能是不必要的。在用户输入的情况下,该模块的许多用户将在数据传递给您的代码之前验证它们的数据。
此外,更长和更复杂的代码将更难维护,更慢地添加新的功能。它也更有可能开发bug。可能有几个地方允许无效的值通过会造成严重的损害,特别是向这些地方添加检查是很好的做法,但是如果有人将错误的参数传递给列表操作函数,然后得到一个错误,那就不是世界末日了。
您最好把时间花在为那些使用JavaScript模块的人编写好的文档上。作为一个额外的优势,这个文档还可以帮助TypeScript用户。
https://stackoverflow.com/questions/73410742
复制相似问题