自学TS(二)

目录

TypeScript变量声明

类型推论(Type Inference)

联合类型(Union Types)

联合类型的属性和方法

联合类型的数组

对象的类型-接口

什么是接口

可选属性

任意属性

只读属性

接口和数组

接口继承


TypeScript变量声明

        变量是计算机中用来存储数据的“容器”,它可以让计算机变得有记忆。

        注意:变量不是数据本身,它们仅仅是一个用于存储数值的容器

        TypeScript变量的命名规范:

                •  变量名称可以包含数字和字母。

                •  变量名称不能以数字开头。

                •  除了_和$符号外,不能包含其他特殊字符,包括空格。

                •  不能使用TypeScript和Javascript内置的一些英语词汇,比如:number、string、enum、void等。

                •  字母严格区分大小写,大小写不一致的变量代表着不同的变量。

        变量使用之前必须声明,可以使用let和var来进行声明。我们可以使用以下四种方式来声明变量。

        声明变量的类型及初始值。

let 变量名: 类型 = 值;
// 例如
let num: number = 123;

        声明变量的初始值,但不设置类型,该变量的类型为初始值的类型。

let 变量名 = 值;
// 例如
let num = 123;
num = 'a';
// Type 'string' is not assignable to type 'number'.
// 类型'string'不能赋值给类型'number'。

        声明变量的类型,但不设置初始值,该变量的初始值为undefined。

let 变量名: 类型;
// 例如
let num: number;
console.log(num);
// undefined

        声明变量,但不设置类型和初始值,该变量的类型为any类型,初始值为undefined。

let 变量名;
// 例如
let num;
console.log(num);
num = 123;
num = 'a';
// undefined

类型推论(Type Inference)

        如果没有明确的指定类型,那么TypeScript会依照类型推论(Type Inference)的规则推断出一个类型。

let num = 2;
num = "12";
// Type 'string' is not assignable to type 'number'.
// 类型'string'不能赋值给类型'number'。

        上述例子中虽然没用指定类型,但是在编译的过程中会报错,事实上以上代码等价于:

let num: number = 2;
num = "12";
// Type 'string' is not assignable to type 'number'.
// 类型'string'不能赋值给类型'number'。

        TypeScript会在没有明确指定一个类型的时候推断出一个类型,这就是类型推论。

        如果定义的时候没有赋值,不管之后哦有没有赋值,都会被推断成any类型而不被类型检查。

let num;
num = 12;
num = "12";

        等价于:

let num: any;
num = 12;
num = "12";

联合类型(Union Types)

        联合类型(Union Types)表示的是取值可以为多种类型中的一种,通过(|)将变量设置为多种类型。

        注意:只能赋值指定类型,如果赋值其它类型就会报错。

let val: string | number;
val = 12;
val = "Runoob";
val = null;
// Type 'null' is not assignable to type 'string | number'.
// 类型'null'不能分配给类型'string | number'。

        上述例子中let val:string|number的含义是,允许val的类型是string或者number,其他类型就会报错。

联合类型的属性和方法

        当TypeScript不确定一个联合类型的变量到底时哪个类型的时候,我们只能访问此联合类型中所有类型的共有的属性和方法

let val: string | number = 123;
console.log(val.length);
// Property 'length' does not exist on type 'number'.
// 属性'length'在类型'number'上不存在。

let val: string | number = "123";
console.log(val.toString());
// 运行正常

        当联合类型当作参数使用时,可以先判断类型,在做进一步的操作。

function log(val: string | string[]) {
    if(typeof val === "string") {
        console.log(val);
    } else {
        val.forEach(item => {
            console.log(item);
        });
    }
}
log("a");
log(["b", "c"]);
// "a"  "b"  "c"

联合类型的数组

        我们还可以将数组声明为联合类型。

let arr :number[] | string[];
arr = [1, 2, 3];
arr.forEach(item => {
    console.log(item);
});
arr = ["a", "b", "c"];
arr.forEach(item => {
    console.log(item);
});
// 1  2  3
// "a"  "b"  "c"

对象的类型-接口

        在 TypeScript中,我们使用接口(Interfaces)来定义对象的类型。

什么是接口

        接口时一系列抽象方法的声明,是一些方法特征的集合,这些方法应该都是抽象的,需要具体的类去实现,然后第三方就可以通过这组抽象方法去调用,让具体的类执行具体的方法。

        TypeScript中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对对象的形状(Shape)进行描述。

interface ICat {
    name: string;
    age: number;
};

let tom: ICat = {
    name: 'Tom',
    age: 25
};

        上述例子中,我们定义了一个接口Cat,接着定义了一个变量tom,他的类型是Cat。这样我们就约束了tom的形状必须和接口Cat一致。

        接口的命名准则:

                •  接口名称可以是名词、名词短语或者是描述行为的形容词。

               •  使用大小写。

                •  谨慎使用小写。

                •  在接口名称前面加上字母I,以表示类型为接口。

                •  定义类/接口的时候,请使用类似的名称。名称之间的区别仅在于接口名称前面有一个字母I

                •  不要使用下划线字符(_)。

        定义的变量比接口多一些属性是不允许的。

interface ICat {
    name: string;
};

let tom: ICat = {
    name: 'Tom',
    age: 25
};
// Type '{ name: string; age: number; }' is not assignable to type 'Cat'.
// 类型'{ name: string; age: number; }'不能赋值给类型'Cat'。
// Object literal may only specify known properties, and 'age' does not exist in type 'Cat'.
// 对象字面量只能指定已知属性,并且'age'在类型'Cat'中不存在。

        定义的变量比接口少一些属性是不允许的。

interface ICat {
    name: string;
    age: number;
};

let tom: ICat = {
    name: 'Tom'
};
// Property 'age' is missing in type '{ name: string; }' but required in type 'Cat'.
// 属性'age'在类型'{name: string;}',但在类型'Cat'中需要。

        所以赋值的时候,变量的形状必须和接口的形状保持一致。

可选属性

        有时候在赋值的时候我们不希望变量的形状和接口保持一致,那么可以使用可选属性:

interface ICat {
    name: string;
    age?: number;
};

let tom: ICat = {
    name: 'Tom'
};
interface ICat {
    name: string;
    age?: number;
};

let tom: ICat = {
    name: 'Tom',
    age: 25
};

        可选属性的含义是该属性可以不存在,但是这时仍然不允许添加未定义的属性或者减少必要的属性。

interface ICat {
    name: string;
    age?: number;
};

let tom: ICat = {
    name: 'Tom',
    age: 25,
    sex: "男"
};
// Type '{ name: string; age: number; sex: string; }' is not assignable to type 'Cat'.
// 类型'{ name: string; age: number; sex: string; }'不能赋值给类型'Cat'。
// Object literal may only specify known properties, and 'sex' does not exist in type 'Cat'.
// 对象字面量只能指定已知属性,而'sex'在类型'Cat'中不存在。
interface ICat {
    name: string;
    age?: number;
};

let tom: ICat = {
    age: 25
};
// Property 'name' is missing in type '{ age: number; }' but required in type 'Cat'.
// 属性“name”在类型“{ age: number; }',但在类型'Cat'中需要。

任意属性

        有时候我们希望一个接口允许有任意的属性,可以使用如下方式:

interface ICat {
    name: string;
    age?: number;
    [propName: string]: string;
};

let tom: ICat = {
    name: 'Tom',
    gender: 'male',
    color: "grey",
};

  [propName: string]: string的意思是,定义了接口中的任意属性为string类型的值。

        需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型必须是它的类型的子集。

interface ICat {
    name: string;
    age?: number;
    [propName: string]: string;
};

let tom: ICat = {
    name: 'Tom',
    gender: 'male',
    color: "grey",
    age: 15
};
// Property 'age' of type 'number | undefined' is not assignable to 'string' index type 'string'.
// 类型为'number | undefined'的属性'age'不能分配给类型为'string'的'string'。
// Type '{ name: string; age: number; gender: string; color: string; }' is not assignable to type 'Cat'.
// 类型'{ name: string; age: number; gender: string; color: string; }'不能赋值给类型'Cat'。
// Property 'age' is incompatible with index signature.
// 属性'age'与索引类型不兼容。
// Type 'number' is not assignable to type 'string'.
// 类型'number'不能赋值给类型'string'。

        上述例子中,任意属性的值允许的类型是string,但是可选属性age的值的类型却是numbernumber不是string的子属性,所以就导致了报错。

        一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以再任意属性中使用联合属性。

interface ICat {
    name: string;
    age: number;
    [propName: string]: string | number;
};

let tom: ICat = {
    gender: 'male',
    color: "grey",
    name: 'Tom',
    age: 15
};

只读属性

        有时候我们希望对象中的一些字段只能再创建的时候被赋值,那么可以用readonly定义只读属性。

interface ICat {
    readonly id: number;
    name: string;
    age: number;
    [propName: string]: string | number;
};

let tom: ICat = {
    id: 9527,
    gender: 'male',
    color: "grey",
    name: 'Tom',
    age: 15
};

tom.id = 3208;
// Cannot assign to 'id' because it is a read-only property.
// 不能分配给'id',因为它是只读属性。

        上述例子中,使用readonly定义的属性id初始化之后,又被赋值了,所以报错了。

        注意,只读的约束存在于第一个给对象赋值的时候,而不是第一次给自读属性赋值的时候。

interface ICat {
    readonly id: number;
    name: string;
    age: number;
    [propName: string]: string | number;
};

let tom: ICat = {
    gender: 'male',
    color: "grey",
    name: 'Tom',
    age: 15
};

tom.id = 3208;
// Property 'id' is missing in type '{ gender: string; color: string; name: string; age: number; }' but required in type 'Cat'.
// 在'Cat'类型中需要类型'{ gender: string; color: string; name: string; age: number; }'中的'id'属性。
// Cannot assign to 'id' because it is a read-only property.
// 不能分配给'id',因为它是只读属性。

        上述例子中,有两处发生了报错,第一个是在给对象tom赋值的时候没有对id进行赋值,发生了报错;第二个是给tom中的只读属性id进行了赋值,发生了报错。

接口和数组

        接口中我们可以将数组的索引值和元素设置为不同的类型,索引值可以是数字或者是字符串。

interface IColor {
    [index: number]: string;
};

let colorArr: IColor = ["red", "pink", "black"];

let colorArr: IColor = ["red", 1, "black"];
// Type 'number' is not assignable to type 'string'.
// 类型'number'不能赋值给类型'string'。

let colorArr: IColor;
colorArr["r"] = "red";
// Element implicitly has an 'any' type because index expression is not of type 'number'.
// 元素隐式具有'any'类型,因为索引表达式不是'number'类型。

        上述例子中,IColor定义一个数组索引值是number类型,值是string类型,如果使用了其他类型则会报错。

interface IColor {
    [index: string]: number;
};

let colorArr: IColor;
colorArr["r"] = 1;

interface IColor {
    [index: string]: string;
};

let colorArr: IColor;
colorArr["r"] = "red";

接口继承

        接口继承就是接口可以通过其他接口来扩展自己,TypeScript中使用extends实现接口继承接口。

        单继承时使用extends继承即可,多继承时,需要继承的每个接口使用,分割。

interface IName {
    name: string;
};

interface ICat extends IName {
    age: number;
};

let tom: ICat = {
    name: "Tom",
    age: 12
};

        上述例子中,ICat继承了IName中的属性,所以在给对象tom赋值的时候IName中的属性和ICat中的属性都要添加。

interface IName {
    name: string;
};

interface IAge {
    age: number;
};

interface ICat extends IName, IAge {};

let tom: ICat = {
    name: "Tom",
    age: 12
};

        上述例子中,ICat继承了INameIAge中的属性,所以在给对象tom赋值的时候IName中的属性和IAge中的属性都要添加。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题是关于FineReport的插入报表的学习。 FineReport是一款功能强大的报表设计软件,可以帮助用户快速创建美观、交互性强的报表。在插入报表的学习中,我们将学习如何在FineReport中插入报表。 首先,我们需要打开FineReport软件,并创建一个新的报表项目。在FineReport的菜单栏中选择“插入”选项,然后选择“报表”选项。接着,会弹出一个报表插入对话框。 在报表插入对话框中,我们可以选择要插入的报表类型。FineReport提供了多种报表类型供选择,如柱状图、饼图、折线图等。我们根据需要选择一个报表类型,并点击“确定”按钮。 接下来,会弹出一个报表设计窗口。在报表设计窗口中,我们可以对报表进行自定义调整。我们可以修改报表的标题、数据源、样式等。在报表设计窗口中,还可以对报表进行数据透视、图表交互、数据筛选等高级操作。 完成对报表的设计后,我们可以保存报表并预览效果。在报表设计窗口中,点击菜单栏中的“保存”按钮,保存我们所设计的报表。然后,点击菜单栏中的“预览”按钮,即可查看刚才设计的报表的效果。 通过以上的操作,我们就可以在FineReport中成功插入一个报表,并对其进行自定义调整。FineReport的强大功能使报表的设计变得简单和灵活,帮助用户轻松创建出满意的报表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值