TS 优秀代码示例

# 枚举+位运算进行状态判断

枚举+位运算进行状态判断与运算, 原文链接 (opens new window)

enum AnimalFlags {
  None        = 0,
  HasClaws    = 1 << 0,
  CanFly      = 1 << 1
}

interface Animal {
  flags: AnimalFlags;
  [key: string]: any;
}

function printAnimalAbilities(animal: Animal) {
  var animalFlags = animal.flags;
  if (animalFlags & AnimalFlags.HasClaws) {
    console.log('animal has claws');
  }
  if (animalFlags & AnimalFlags.CanFly) {
    console.log('animal can fly');
  }
  if (animalFlags == AnimalFlags.None) {
    console.log('nothing');
  }
}

var animal = { flags: AnimalFlags.None };
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws;
printAnimalAbilities(animal); // animal has claws
animal.flags &= ~AnimalFlags.HasClaws;
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly;
printAnimalAbilities(animal); // animal has claws, animal can fly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  • Animal 有多种状态时判断、运算十分简洁

  • 用数字、二进制表示某种状态时,枚举能语义化字段的含义,又能用于真实环境的数据传输

假如让我来写的话,不用枚举+位运算的话可能实现如下

type AnimalFlags = 'None' | 'HasClaws' | 'CanFly';
interface Animal {
  flags: AnimalFlags[];
  [key: string]: any;
}

function printAnimalAbilities(animal: Animal) {
  var animalFlags = animal.flags;
  if (!animalFlags || animalFlags.includes('None')) {
    return 'nothing';
  }
  if (animalFlags.includes('HasClaws')) {
    console.log('animal has claws');
  }
  if (animalFlags.includes('CanFly')) {
    console.log('animal can fly');
  }
}

var animal: Animal = { flags: ['None'] };
printAnimalAbilities(animal); // nothing
animal.flags = ['HasClaws'];
printAnimalAbilities(animal); // animal has claws
animal.flags = ['None'];
printAnimalAbilities(animal); // nothing
animal.flags = ['HasClaws', 'CanFly'];
printAnimalAbilities(animal); // animal has claws, animal can fly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

运算不太方便,比如状态是['HasClaws', 'CanFly'], 想移除Fly状态得找到元素位置、操作数组,等操作相比前面一种方式麻烦太多

# 简写技巧

可选项变必选

type Concrete<Type> = {
  [Property in keyof Type]-?: Type[Property];
};
1
2
3

# React 导出 useImperativeHandle 声明

参考:https://stackoverflow.com/questions/62210286/declare-type-with-react-useimperativehandle

定义:

type CountdownProps = {}
    
type CountdownHandle = {
  start: () => void,
}
    
const Countdown: React.ForwardRefRenderFunction<CountdownHandle, CountdownProps> = (
  props,
  forwardedRef,
) => {
  React.useImperativeHandle(forwardedRef, ()=>({
    start() {
      alert('Start');
    }
  });

  return <div>Countdown</div>;
}

export default React.forwardRef(Countdown);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

使用:

const App: React.FC = () => {
  // this will be inferred as `CountdownHandle`
  type CountdownHandle = React.ElementRef<typeof Countdown>;

  const ref = React.useRef<CountdownHandle>(null); // assign null makes it compatible with elements.

  return (
    <Countdown ref={ref} />
  );
};
1
2
3
4
5
6
7
8
9
10