添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
console . log ( fn ( ) ) ; // => undefined

需要注意的是,在 TypeScript 中,如果我们显式声明函数的返回值类型为 undfined ,将会得到如下所示的错误提醒。

function fn(): undefined { // ts(2355) A function whose declared type is neither 'void' nor 'any' must return a value
  // TODO

此时,正确的做法是使用 void 类型来表示函数没有返回值的类型(这是“废柴” void 类型唯一有用的场景),示例如下:

function fn1(): void {
fn1().doSomething(); // ts(2339) Property 'doSomething' does not exist on type 'void'

我们可以使用类似定义箭头函数的语法来表示函数类型的参数和返回值类型,此时=> 类型仅仅用来定义一个函数类型而不用实现这个函数。

需要注意的是,这里的=>与 ES6 中箭头函数的=>有所不同。TypeScript 函数类型中的=>用来表示函数的定义,其左侧是函数的参数类型,右侧是函数的返回值类型;而 ES6 中的=>是函数的实现。

在对象(即接口类型)中,除了使用这种声明语法,我们还可以使用类似对象属性的简写语法来声明函数类型的属性,如:

interface Entity {
    add: (a: number, b: number) => number;
    del(a: number, b: number): number;
const entity: Entity = {
    add: (a, b) => a + b,
    del(a, b) {
      return a - b;

在某种意义上来说,这两种形式都是等价的。但是很多时候,我们不必或者不能显式地指明返回值的类型,这就涉及可缺省和可推断的返回值类型的讲解。

可缺省和可推断的返回值类型

幸运的是,函数返回值的类型可以在 TypeScript 中被推断出来,即可缺省。

函数内是一个相对独立的上下文环境,我们可以根据入参对值加工计算,并返回新的值。从类型层面看,我们也可以通过类型推断加工计算入参的类型,并返回新的类型,示例如下:

function computeTypes(one: string, two: number) {
  const nums = [two];
  const strs = [one]
  return {
    nums,
  } // 返回 { nums: number[]; strs: string[] } 的类型 

请记住:这是一个很重要也很有意思的特性,函数返回值的类型推断结合泛型可以实现特别复杂的类型推断,比如 Redux Model 中 StateReducerEffect 类型的关联。

一般情况下,TypeScript 中的函数返回值类型是可以缺省和推断出来的,但是有些特例需要我们显式声明返回值类型,比如 Generator 函数的返回值。

Generator 函数的返回值

ES6 中新增的 Generator 函数在 TypeScript 中也有对应的类型定义。

Generator 函数返回的是一个 Iterator 迭代器对象,我们可以使用 Generator 的同名接口泛型或者 Iterator 的同名接口泛型表示返回值的类型(Generator 类型继承了 Iterator 类型),示例如下:

type AnyType = boolean;
type AnyReturnType = string;
type AnyNextType = number;
function *gen(): Generator<AnyType, AnyReturnType, AnyNextType> {
  const nextValue = yield true; // nextValue 类型是 number,yield 后必须是 boolean 类型
  return `${nextValue}`; // 必须返回 string 类型

注意:TypeScript 3.6 之前的版本不支持指定 nextreturn 的类型,所以在某些有点历史的代码中,我们可能会看到 Generator 和 Iterator 类型不一样的表述。

关于 JS 中函数的参数,在es6之后,统共可以分为:可选参数、默认参数、剩余参数 几个特性。

可选参数和默认参数

在实际工作中,我们可能经常碰到函数参数可传可不传的情况,当然 TypeScript 也支持这种函数类型表达,如下代码所示:

function log(x?: string) {
  return x;
log(); // => undefined
log('hello world'); // => hello world

在上述代码中,我们在类型标注的:前添加?表示 log 函数的参数 x 就是可缺省的。

也就是说参数 x 的类型可能是 undefined(第 5 行调用 log 时不传入实参)类型或者是 string 类型(第 6 行调用 log 传入 'hello world' 实参),那是不是意味着可缺省和类型是 undefined 等价呢?

function log(x?: string) {
  console.log(x);
function log1(x: string | undefined) {
  console.log(x);
log();
log(undefined);
log1(); // ts(2554) Expected 1 arguments, but got 0
log1(undefined);

显而易见:这里的 ?: 表示参数可以缺省、可以不传,但如果传则一定是string类型。也就是说调用函数时,我们可以不显式传入参数。但是,如果我们声明了参数类型为 xxx | undefined,就表示函数参数是不可缺省且类型必须是 xxx 或者 undfined。

因此,在上述代码中,log1 函数如果不显示传入函数的参数,TypeScript 就会报一个 ts(2554) 的错误,即函数需要 1 个参数,但是我们只传入了 0 个参数。

在 ES6 中支持函数默认参数的功能。而 TypeScript 会根据函数的默认参数的类型来推断函数参数的类型,示例如下:

function log(x = 'hello') {
    console.log(x);
log(); // => 'hello'
log('hi'); // => 'hi'
log(1); // ts(2345) Argument of type '1' is not assignable to parameter of type 'string | undefined'

在上述示例中,根据函数的默认参数 'hello' ,TypeScript 推断出了 x 的类型为 string | undefined

当然,对于默认参数,TypeScript 也可以显式声明参数的类型(一般默认参数的类型是参数类型的子集时,我们才需要这么做)。不过,此时的默认参数只起到参数默认值的作用,如下代码所示:

function log1(x: string = 'hello') {
    console.log(x);
// ts(2322) Type 'string' is not assignable to type 'number'
function log2(x: number = 'hello') {
    console.log(x);
log2();
log2(1);
log2('1'); // ts(2345) Argument of type '"1"' is not assignable to parameter of type 'number | undefined'

上例函数 log2 中,我们显式声明了函数参数 x 的类型为 number,表示函数参数 x 的类型可以不传或者是 number 类型。因此,如果我们将默认值设置为字符串类型,编译器就会抛出一个 ts(2322) 的错误。

同理,如果我们将函数的参数传入了字符串类型,编译器也会抛出一个 ts(2345) 的错误。

请再次注意:函数的默认参数类型必须是参数类型的子类型

function log3(x: number | string = 'hello') {
    console.log(x);

在上述代码中,函数 log3 的函数参数 x 的类型为可选的联合类型 number | string,但是因为默认参数字符串类型是联合类型 number | string 的子类型,所以 TypeScript 也会检查通过。

在 ES6 中,JavaScript 支持函数参数的剩余参数,它可以把多个参数收集到一个变量中。同样,在TypeScript 中也支持这样的参数类型定义,如下代码所示:

function sum(...nums: number[]) {
    return nums.reduce((a, b) => a + b, 0);
sum(1, 2); // => 3
sum(1, 2, 3); // => 6
sum(1, '2'); // ts(2345) Argument of type 'string' is not assignable to parameter of type 'number'

在上述代码中,sum 是一个求和的函数,...nums将函数的所有参数收集到了变量 nums 中,而 nums 的类型应该是 number[],表示所有被求和的参数是数字类型。因此,sum(1, '2') 抛出了一个 ts(2345) 的错误,因为参数 '2' 并不是 number 类型。

如果我们将函数参数 nums 聚合的类型定义为 (number | string)[],如下代码所示:

function sum(...nums: (number | string)[]): number {
    return nums.reduce<number>((a, b) => a + Number(b), 0);
sum(1, '2', 3); // 6

那么,函数的每一个参数的类型就是联合类型 number | string,因此 sum(1, '2', 3) 的类型检查也就通过了。

typescript中的常见报错:

  • ts(2322)是一个静态类型检查的错误,在注解的类型和赋值的类型不同的时候就会抛出这个错误
  • ts(2355) :简单来说就是:函数必须有一个返回值(报错翻译:声明类型既不是void也不是any的函数必须返回一个值)
  • ts(2339): 在TypeScript中如果按JS的方式去获取对象属性时,可能会遇到。它表示Typescript在执行代码检查时在该对象没有定义相应属性。解决方法有 —— 直接设置对象为any、对象断言为any、将属性.获取方式改为数组式获取三种
  • ts(2345):参数类型与预期不符
  • ts(2554):参数个数与预期不符
返回值类型在 JavaScript 中,我们知道一个函数可以没有显式 return,此时函数的返回值应该是 undefined:function fn() { // TODO}console.log(fn()); // =&gt; undefined需要注意的是,在 TypeScript 中,如果我们显式声明函数的返回值类型为 undfined,将会得到如下所示的错误提醒。function fn(): undefined { // ts(2355) A function whose dec
前面我们讲到过ts的静态类型定义中的函数类型定义,先来回顾下: const fnA: () => string = () => { return '1' } const fnB: () => number = () => 6 const fnC: () => boolean = () => true 拓展下:在接口中如何定义函数类型呢?接口后期会讲 interface Ifn { (one: number, two: number): number 0:类型,1:类型列表,2:类型列表 推断变量{0}具有不兼容的边界等式约束:{1}上限:{2} Error:(16, 39) java: no suitable method found for convert(java.lang.Class<FooEntity>,java.lang.String,java.math.BigDecimal) method InvalidType.<ENTITY>convert(java.lang.Class<ENTITY>,java.lang.String,java.lang.Object) is not applicable (inference variable ENTITY has incompatible bounds equality constraints: FooEntity
TypeScript error TS2345:Argument of type 'String' is not assignable to parameter of type 'string'
* @Date: 2018-11-01 20:07:29 * @Last Modified by: AK-12 * @Last Modified time: 2018-11-01 22:00:41 import IBlock from './IBlock' export default class Block implements I...
```typescript let obj1: {}; // 约束该变量的类型为对象 let obj2: { name: string }; // 约束该变量的类型为 [有且只有 name 属性的] 对象, 且 name 的属性值的类型必须是 string - 可以直接给变量赋值,TS 会自动识别类型,并对变量进行约束 ```typescript let obj = { width: 200 }; // 此时 ob
现在好多前端框架都开始支持typescript,ts本身支持es5和es6写法,但是ts本身对js语法进行了进一步封装,vue3.0开始全面支持,但是惭愧自己一直不了解ts,趁着这两天有时间,自己总结下,欢迎评论留言交流,如有不对的地方,会及时更正,还望见谅 1.全局安装typescript npm install typescript -g 2,编译ts文件 1,新建文件 index...
// string 类型 let firstName: string = 'viking' let message: string = `Hello, ${firstName}, age is ${age}` // undefined 和 null 是所有类型的子类型
背景Javascript 是一门弱类型语言。与 Java、C++ 等强类型语言不同。Javascript 通过 var 关键字声明变量(ECMAScript 6 开始允许使用 let / const 声明变量),系统会在赋值语句中自动判断其数据类型。优点:书写简洁灵活var a = 1; var b = 'hello'; 缺点:类型不可预测,易造成程序运行结果不符合预期var a = 2; var...
const total = getTotal(1, 2); 这时候我们写的代码其实是有一个小坑的,就是我们并没有定义getTotal的返回值类型,虽然TypeScript可以自己推断出返回值是number类型。 但是如果这时候我们的代码写错了,比如写程了下面这个样子。 function getTotal(one: number, two:
JavaScriptTypeScript 里,我们会经常遇到不需要给函数命名的情况,尤其是在需要将一个函数作为参数传给另外一个函数的时候。 这时,我们会创建 匿名函数 。 因为这些函数不会在其他地方复用,所以我们不需要给它们命名。 这种情况下,我们通常会使用以下语法: const myFunc = function() { const myVar = "value"; return myVar; ES6 提供了其他写匿名函数的方式的语法糖。 你可以使用 **箭头函数 **:
最近在对接谷歌的localhomeSDK,详情看这里https://aijishu.com/a/1060000000011433,【后续对接完成会写一篇踩坑的血泪史==】应用他们的sdk需要的语言可用js或者ts,因为他们sdk的demo为ts,无奈又要去学ts, 作为一个渣渣,对接,踩坑,语言,踩坑,测试,踩坑,至今还在坑里。。。 ts语言,之前没什么了解,就在菜鸟教程看了他的语法,就开始了,初生牛犊不怕虎哈哈哈哈,前面还好,跟着菜鸟教程查阅就好,下发指令对接时候吗,就gg了。 按照js写法声明结构体,数
类型约可以约束什么? 有变量、函数的参数、函数的返回值;在定义变量时就先告诉它该变量是什么类型; 在定义函数参数时约束参数类型还有参数返回值类型等;等到在使用这些变量、参数返回值时就会进行类型检查,看你有没有违反约束 如何约束? 仅需要在变量、函数的参数、函数的返回值位置上加上:类型 变量let name:string;注意这个类型是小写的不是大写的;如果后面..
静态类型语言 如果变量的类型在编译时是已知的,那么语言就是静态类型的。对于某些语言来说,必须指定每个变量的类型(例如:Java、C、c++);其他语言提供了某种形式的类型推断,即类型系统推断变量类型的能力(例如:OCaml、Haskell、Scala、Kotlin)。 主要优点是所有类型的检查都可以由编译器完成,因此在非常早期的阶段就可以捕捉到很多小错误。 示例:C,C ++,Java,Rust,Go,Scala 动态类型语言 如果一种语言的类型与运行时值相关联,而不是命名变量/字段/等等,那么它就是动态类