013 --TypeScript之高级类型
交叉类型可以简单理解为将多个类型合并成一个类型
function extend<T, U>(first: T, second: U): T & U {
let result = {} as T & U
for(let id in first) {
result[id] = first[id] as any
}
for(let id in second){
if(!result.hasOwnProperty(id)){
result[id] = second[id] as any
}
}
return result
}
//为了编译通过,我们让上述的first[id],second[id]断言成了any
class Person {
constructor(public name: string){
}
}
interface loggable {
log(): void
}
class ConsoleLogger implements loggable {
log(){
}
}
var jim = extend(new Person('jim'), new ConsoleLogger())
//通过extend函数使两个class扩展到一起,称为交叉类型
jim.name
jim.log()
编译后
function extend(first, second) {
var result = {};
for (var id in first) {
result[id] = first[id];
}
for (var id in second) {
if (!result.hasOwnProperty(id)) {
result[id] = second[id];
}
}
return result;
}
//为了编译通过,我们让上述的first[id],second[id]断言成了any
var Person = /** @class */ (function () {
function Person(name) {
this.name = name;
}
return Person;
}());
var ConsoleLogger = /** @class */ (function () {
function ConsoleLogger() {
}
ConsoleLogger.prototype.log = function () {
};
return ConsoleLogger;
}());
var jim = extend(new Person('jim'), new ConsoleLogger());
//通过extend函数使两个class扩展到一起,称为交叉类型
jim.name;
jim.log();
联合类型
function padLeft(value: string, padding: any/*string | number */) {
if(typeof padding === 'number'){
return Array(padding + 1).join(' ') + value
}
if(typeof padding === 'string') {
return padding + value
}
throw new Error(`Expected string or number got ${padding}`)
}
console.log(padLeft('Hello world', 5))// Hello world
console.log(padLeft('Hello world', '123'))//123Hello world
//console.log(padLeft('Hello world', true))//这样写也不会报错,因为padding是any
//什么是联合类型呢,就是如果给padding做约束,就是padding: string | number
联合类型和交叉类型的区别是什么?联合类型是几种之一,交叉类型是几种类型之和
interface Bird {
fly()
layEggs()
}
interface Fish {
swim()
layEggs()
}
function getSmallPet(): Fish | Bird {
return //...
}
let pet = getSmallPet()
pet.layEggs()
//pet.swim()//报错,因为上面声明了是联合类型
//getSmallPet只能是Fish或者Bird
//所以只能调用它们共有的方法
类型保护
上述例子中我们如何判断是哪个类型呢
interface Bird {
fly()
layEggs()
}
interface Fish {
swim()
layEggs()
}
function getSmallPet(): Fish | Bird {
return //...
}
let pet = getSmallPet()
if (isFish(pet)){
pet.swim()
} else {
pet.fly()
}
//类型谓词的类型保护机制
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined
}
function isNumber(x: any): x is number {
return typeof x === 'number'
}
function isString(x: any): x is string {
return typeof x === 'string'
}
function padLeft(value: string, padding: string | number){
if (isNumber(padding)) {
return Array(padding + 1).join('') + value
}
if (isString(padding)) {
return padding + value
}
throw new Error(`Expected string or number, got ${padding}`)
}
typeof的类型保护机制
//typeof对基础类型提供类型保护,可以直接推断出值的类型,而不必像上例那样写
//一般 === 和 !==提供保护
//其他的可以用谓词保护
function padLeft(value: string, padding: string | number){
if (typeof padding === 'number') {
return Array(padding + 1).join('') + value
}
if (typeof padding === 'string') {
return padding + value
}
throw new Error(`Expected string or number, got ${padding}`)
instanceof类型保护
class Bird {
fly() {
console.log('bird fly')
}
layEggs(){
console.log('bird lay eggs')
}
}
class Fish {
swim(){
console.log('fish swimming')
}
layEggs(){
console.log('fish lay eggs')
}
}
function getRandomPet(): Fish | Bird {
return Math.random() > 0.5 ? new Bird() : new Fish()
}
let pet = getRandomPet()
if (pet instanceof Bird) {
pet.fly()
}
if (pet instanceof Fish) {
pet.swim()
}
null和undefined
回顾之前的代码
let s = null
s = null
let sn: string | null = 'bar'
sn = null
sn = undefined
//这段代码在编译时是不会出错的
//加上参数 --strictNullChecks会编译出错
function f(x: number, y?: number){
return x + (y || 0)
}
f(1,2)
f(1)
f(1,undefined)
//f(1,null)报错
// 'null' is not assignable to parameter of type 'number | undefined'.
在类中也是一样
class C {
a:number
b?:number//相当于联合类型number | undefined
}
let c = new C()
c.a = 12
c.a = undefined //报错,a为number
c.b = 13
c.b = undefined
c.b = null //报错
null的类型保护和类型断言
function broken(name: string | null ): string {
function postfix(epither: string) {
return name!.charAt(0) + '. the' + epither
}
name = name || 'Bob'
return postfix(name)
}
//上述函数在编译时出错 --strictNullChecks
//ts编译器不知道name是否为null
//我们可以用类型断言方式给name加上!表示name不为null
高级类型之字符串字面量类型
type Easing = 'ease-in' | 'ease-out' | 'ease-in-out'
class UIElement {
animate(dx: number, dy: number,easing: Easing) {
if (easing === 'ease-in') {
//...
} else if (easing === 'ease-out') {
}else if (easing === 'ease-in-out') {
}else {
}
}
}
let button = new UIElement()
button.animate(0, 0, 'ease-in')
//button.animate(0, 0, null)//编译时报错
//Argument of type 'null' is not assignable to parameter of type 'Easing'.
2019-05-30 09:53:16
转载于//www.cnblogs.com/ccbest/p/10945225.html
还没有评论,来说两句吧...