or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtin-types.mdindex.mdproperty-types.mdsymbol-analysis.mdtype-analysis.mdtype-constraints.mdtype-predicates.mdtype-safety.mdtype-specifiers.md

type-constraints.mddocs/

0

# Type Constraints and Context

1

2

Tools for working with TypeScript's type constraint system and contextual typing. These utilities are essential for understanding generic types, type inference, and the relationships between types in different contexts.

3

4

## Capabilities

5

6

### Type Constraint Resolution

7

8

Functions for resolving generic type constraints and understanding type parameter relationships.

9

10

```typescript { .api }

11

/**

12

* Resolves a node's type, returning the type's generic constraint if it has one.

13

* Warning: If the type is generic without a constraint, returns the type as-is

14

* rather than `unknown`. Check for ts.TypeFlags.TypeParameter to detect this case.

15

*/

16

function getConstrainedTypeAtLocation(

17

services: ParserServicesWithTypeInformation,

18

node: TSESTree.Node

19

): ts.Type;

20

```

21

22

**Usage Examples:**

23

24

```typescript

25

import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";

26

import * as ts from "typescript";

27

28

// In an ESLint rule

29

export default {

30

create(context) {

31

const services = context.parserServices;

32

33

return {

34

FunctionDeclaration(node) {

35

// Get the constrained type for a function parameter

36

if (node.params.length > 0) {

37

const param = node.params[0];

38

const constrainedType = getConstrainedTypeAtLocation(services, param);

39

40

// Check if it's a type parameter without constraint

41

if (constrainedType.flags & ts.TypeFlags.TypeParameter) {

42

// Handle unconstrained type parameter

43

context.report({

44

node: param,

45

messageId: "unconstrainedGeneric"

46

});

47

}

48

}

49

}

50

};

51

}

52

};

53

```

54

55

### Contextual Type Analysis

56

57

Functions for understanding the contextual type expectations in TypeScript expressions.

58

59

```typescript { .api }

60

/**

61

* Returns the contextual type of a given node - the type of the target

62

* the node is going into (e.g., function parameter type, variable declaration type)

63

*/

64

function getContextualType(checker: ts.TypeChecker, node: ts.Expression): ts.Type | undefined;

65

```

66

67

**Usage Examples:**

68

69

```typescript

70

import { getContextualType } from "@typescript-eslint/type-utils";

71

72

// In an ESLint rule checking function arguments

73

export default {

74

create(context) {

75

const services = context.parserServices;

76

const checker = services.program.getTypeChecker();

77

78

return {

79

CallExpression(node) {

80

// Check each argument against its expected contextual type

81

node.arguments.forEach((arg, index) => {

82

const tsArg = services.esTreeNodeToTSNodeMap.get(arg);

83

const contextualType = getContextualType(checker, tsArg);

84

85

if (contextualType) {

86

const actualType = checker.getTypeAtLocation(tsArg);

87

88

// Compare actual vs expected type

89

if (!checker.isTypeAssignableTo(actualType, contextualType)) {

90

context.report({

91

node: arg,

92

messageId: "typeArgumentMismatch",

93

data: {

94

expected: checker.typeToString(contextualType),

95

actual: checker.typeToString(actualType)

96

}

97

});

98

}

99

}

100

});

101

}

102

};

103

}

104

};

105

```

106

107

## Advanced Constraint Analysis

108

109

### Generic Type Constraint Checking

110

111

```typescript

112

// Example: Analyzing generic constraints in function declarations

113

import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";

114

import * as ts from "typescript";

115

116

function analyzeGenericConstraints(

117

services: ParserServicesWithTypeInformation,

118

functionNode: TSESTree.FunctionDeclaration

119

) {

120

if (functionNode.typeParameters) {

121

functionNode.typeParameters.params.forEach(typeParam => {

122

const constrainedType = getConstrainedTypeAtLocation(services, typeParam);

123

124

if (constrainedType.flags & ts.TypeFlags.TypeParameter) {

125

// Unconstrained type parameter

126

console.log(`Unconstrained type parameter: ${typeParam.name.name}`);

127

} else {

128

// Has constraint

129

const checker = services.program.getTypeChecker();

130

const constraintName = checker.typeToString(constrainedType);

131

console.log(`Type parameter ${typeParam.name.name} constrained to: ${constraintName}`);

132

}

133

});

134

}

135

}

136

```

137

138

### Contextual Type Validation

139

140

```typescript

141

// Example: Validating array literal elements against contextual type

142

import { getContextualType } from "@typescript-eslint/type-utils";

143

144

function validateArrayLiteralTypes(

145

services: ParserServicesWithTypeInformation,

146

arrayNode: TSESTree.ArrayExpression

147

) {

148

const checker = services.program.getTypeChecker();

149

const tsArrayNode = services.esTreeNodeToTSNodeMap.get(arrayNode);

150

const contextualType = getContextualType(checker, tsArrayNode);

151

152

if (contextualType && checker.isArrayType(contextualType)) {

153

const elementType = checker.getTypeArguments(contextualType as ts.TypeReference)[0];

154

155

arrayNode.elements.forEach(element => {

156

if (element) {

157

const tsElement = services.esTreeNodeToTSNodeMap.get(element);

158

const elementActualType = checker.getTypeAtLocation(tsElement);

159

160

if (!checker.isTypeAssignableTo(elementActualType, elementType)) {

161

console.log("Array element type mismatch");

162

}

163

}

164

});

165

}

166

}

167

```

168

169

### Inference Context Analysis

170

171

```typescript

172

// Example: Understanding type inference in variable declarations

173

import { getContextualType, getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";

174

175

function analyzeTypeInference(

176

services: ParserServicesWithTypeInformation,

177

variableDeclarator: TSESTree.VariableDeclarator

178

) {

179

const checker = services.program.getTypeChecker();

180

181

// Get the declared type constraint

182

if (variableDeclarator.id.typeAnnotation) {

183

const declaredType = getConstrainedTypeAtLocation(services, variableDeclarator.id);

184

console.log(`Declared type: ${checker.typeToString(declaredType)}`);

185

}

186

187

// Get the contextual type from initializer

188

if (variableDeclarator.init) {

189

const tsInit = services.esTreeNodeToTSNodeMap.get(variableDeclarator.init);

190

const contextualType = getContextualType(checker, tsInit);

191

192

if (contextualType) {

193

console.log(`Contextual type: ${checker.typeToString(contextualType)}`);

194

}

195

196

// Compare inferred vs contextual

197

const inferredType = checker.getTypeAtLocation(tsInit);

198

console.log(`Inferred type: ${checker.typeToString(inferredType)}`);

199

}

200

}

201

```

202

203

## Common Patterns

204

205

### Generic Function Analysis

206

207

```typescript

208

// Analyze generic function constraints and usage

209

function analyzeGenericFunction(node: TSESTree.FunctionDeclaration, services: ParserServicesWithTypeInformation) {

210

const checker = services.program.getTypeChecker();

211

212

// Check type parameters

213

if (node.typeParameters) {

214

node.typeParameters.params.forEach(param => {

215

const constrainedType = getConstrainedTypeAtLocation(services, param);

216

// Analyze constraint

217

});

218

}

219

220

// Check parameter contextual types

221

node.params.forEach(param => {

222

if (param.type === "Identifier" && param.init) {

223

const tsInit = services.esTreeNodeToTSNodeMap.get(param.init);

224

const contextualType = getContextualType(checker, tsInit);

225

// Validate default parameter against contextual type

226

}

227

});

228

}

229

```