Javascript 为什么我必须在TS函数类型中指定参数名?
我正在使用typescript编写一些函数,这是TS接受的函数:Javascript 为什么我必须在TS函数类型中指定参数名?,javascript,typescript,generics,typescript-generics,Javascript,Typescript,Generics,Typescript Generics,我正在使用typescript编写一些函数,这是TS接受的函数: export const useSomething = <T>() => { const useStorage = <T>(key: string, initialData: T) : [T, (newData: T) => Promise<void>] => { const [data, setState] = useState<T>(in
export const useSomething = <T>() => {
const useStorage = <T>(key: string, initialData: T) : [T, (newData: T) => Promise<void>] => {
const [data, setState] = useState<T>(initialData);
const setData = async(newData: T) : Promise<void> => {
await storage.setItem<T>(key, newData);
};
return [data, setData];
}
};
为什么TypeScript要我在
T
发生之前写下newData
名称?好吧,您正在定义一个参数,参数需要名称。否则,您将如何引用它?我的意思是,在调用setItem
时,您正在使用newData
。您不能简单地使用setItem(t)
,它将类似于使用setItem(string)
,这肯定不是您想要的。
我说“类似”,因为
string
在JavaScript中是一个有效的对象,您可以将其作为参数传递<但是,code>T可以是任何东西,可能只是一个类型定义,并且这些类型在编译过程中消失。我认为您最希望得到规范答案的是GitHub问题和。情况的要点是:
函数类型中支持的参数名作为库中函数和方法的文档很有用。函数类型(用户名:string,密码:string)=>void
与(arg0:string,arg1:string)=>void
的类型相同,但前者可能比后者更能帮助开发人员编写代码。因此,我们打算在函数类型中支持类型注释参数名称,并将其记录在中(越来越过时),并在各地的库中使用
我。。。相信它有助于文档编制。以我现有的能力使用Haskell之后,我会说省略参数名。。。在学习新图书馆的时候,对任何人都没有帮助。虽然有一些关于更简单语法的话要说,但类型作为人们文档的唯一形式,常常使理解意图变得困难
此外,如果TypeScript中支持命名值上的类型注释,则可以省略这些类型,并且编译器将对它们进行推断。未能推断出任何有用的结果将导致推断出
any
。例如,在以下函数中:
function f(x, y): void { }
type F = typeof f;
// type F = (x: any, y: any) => void
x
和y
的类型被推断为any
(使用--noImplicitAny
可以得到一个很好的错误)。与以下注释版本相同:
function g(x: any, y: any): void { }
type G = typeof g;
// type G = (x: any, y: any) => void
对f
和g
本身的类型签名应用相同的规则会导致以下行为:
type Fprime = (x, y) => void; // --noImplicitAny yells at you here
// type Fprime = (x: any, y: any) => void
type Gprime = (x: any, y: any) => void;
// type Gprime = (x: any, y: any) => void
因此,当您编写(x,y)=>void
时,编译器将x
和y
解释为名称,而不是类型。因为类型可以省略,所以参数名不能省略。我不认为有人喜欢这样,但这种方式已经存在很长时间了,所以改变它会破坏现实世界的代码。根据上面引用的同一评论:
我认为现在做出这样的改变已经太晚了。由于当前的行为,将单个标识符解释为类型将是一个突破性的变化
这就是这个问题的悲哀答案。也许,如果他们能回到过去,他们会使参数名是可选的,类型是必需的,以便与类型理论符号更紧密地对齐,但现在这是我们所坚持的 希望有帮助;祝你好运
以下类型别名可用于避免显式参数名称:
type F<A extends unknown[], R> = (...args: A) => R
const example1: F<[number, boolean], number> = (x, y) => y ? x : x + 1;
const example2: F<[number], string> = String;
type F=(…args:A)=>R
常数示例1:F=(x,y)=>y?x:x+1;
常量示例2:F=字符串;
我没有定义参数,而是定义一个返回类型,如果返回类型不是匿名的(泛型不是匿名的),则返回类型与变量名无关。我仍然真诚地相信[T,(T)=>Promise]
语法没有错。您不使用setItem(T),而是使用setItem(key)将键转换为T类型。这个答案并没有真正解决这个问题,这就是为什么函数类型需要参数名。类型(x:T)=>void
和(y:T)=>void
是相同的;参数名称是一个伪名称。我假设支持它们的原因是为了文档(类型为(用户名:string,密码:string)=>void
的函数在文档中比(string,string)=>void
更有用),需要它们的原因是一致性和易于解析,但这些只是我的猜测,我还没有标准答案。这是一个非常令人疲惫和有价值的答案——谢谢。使用TypeScript有时很奇怪,因为它解决了一些问题,但也带来了其他问题。匿名类型的值可以表示为:T
,这有点混乱,但也比一个字母名称更明确,更不混乱,或者将复杂的类型延伸到几行,以便为半有意义的名称腾出空间。
type F<A extends unknown[], R> = (...args: A) => R
const example1: F<[number, boolean], number> = (x, y) => y ? x : x + 1;
const example2: F<[number], string> = String;