Skip to content

Commit 34e58cc

Browse files
authored
prefeature: requires justification when throwing actionable errors (#282)
- before, all actionable errors that were thrown anyway were given the same boilerplate message - now, it's more obvious that bypassing error handling warrants explicit justification
1 parent 073cc3b commit 34e58cc

File tree

12 files changed

+36
-39
lines changed

12 files changed

+36
-39
lines changed

src/library/Attempt/Outcome.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const failureDueTo = <
122122
isSuccess : false,
123123
isFailure : true,
124124
optionallyUnwrap: () => null,
125-
forciblyUnwrap : () => givenCause.throwAnyway(),
125+
forciblyUnwrap : () => givenCause.throwAnyway('Unexpected forceful unwrap of a failure'),
126126
causeOfFailure : givenCause,
127127
});
128128

src/library/Attempt/error/ActionableError.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ abstract class ActionableError<SomeBrand extends string>
1212
implements Branded<SomeBrand> {
1313
public readonly brand!: SomeBrand;
1414

15-
public throwAnyway(): never {
16-
return NonActionableError.throw(
17-
'Implementation not specified for actionable error',
18-
{
19-
cause: this,
20-
},
21-
);
15+
public throwAnyway(
16+
givenJustification: string,
17+
): never {
18+
return NonActionableError.throw(givenJustification, {
19+
cause: this,
20+
});
2221
}
2322
}
2423

src/library/Attempt/error/modifier/SafelyPropagated.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ export const assertSafelyPropagated = <
1616
>(
1717
givenError: SomePotentiallyActionableError,
1818
): SafelyPropagated<SomePotentiallyActionableError> => {
19-
// Propagated beyond confines of type system
20-
// i.e. with raw `throw` instead of `.throwAnyway()` method
2119
if (
2220
givenError instanceof ActionableError
23-
) return givenError.throwAnyway();
21+
) return givenError.throwAnyway('Unexpected raw `throw` of some `ActionableError`. If this was intentional, use `.throwAnyway(...)` on the instance instead.');
2422

2523
return givenError as SafelyPropagated<SomePotentiallyActionableError>;
2624
};

src/library/Base64/CharacterSequence/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const CharacterSequence_pattern = new RegExp(`^[${Base64_Alphabet.pattern.source
77
const assertConformanceOf = (givenCharacterSequence: string): string => {
88
if (
99
!CharacterSequence_pattern.test(givenCharacterSequence)
10-
) return new Base64_CharacterSequence_ConformanceError().throwAnyway();
10+
) return new Base64_CharacterSequence_ConformanceError().throwAnyway('To be converted to `Attempt` failure');
1111

1212
return givenCharacterSequence;
1313
};

src/library/Byte/Sequence/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const Byte_Sequence_assertEncodable = (
1616

1717
if (
1818
givenSequence.length % byteCofactor !== 0
19-
) return new Byte_Sequence_EncodingCompatibilityError(givenBitWidth).throwAnyway();
19+
) return new Byte_Sequence_EncodingCompatibilityError(givenBitWidth).throwAnyway('To be converted to `Attempt` failure');
2020

2121
return givenSequence;
2222
};

src/library/customTypes/NonTrivialString/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class NonTrivialString
1818

1919
if (
2020
isEmpty(trimmedSubject)
21-
) return new NonTrivialString_ParsingError(givenSubject).throwAnyway();
21+
) return new NonTrivialString_ParsingError(givenSubject).throwAnyway('To be converted to `Attempt` failure');
2222

2323
return new NonTrivialString(givenSubject);
2424
}

src/library/customTypes/URLComponent/URLOrigin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class URLOrigin
2929
) return new URLOrigin_ParsingError({
3030
expectation: derived.origin,
3131
reality : givenSubject,
32-
}).throwAnyway();
32+
}).throwAnyway('To be converted to `Attempt` failure');
3333

3434
return new URLOrigin(derived.origin);
3535
}

src/library/customTypes/URLComponent/URLPath.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class URLPath
2929
) return new URLPath_ParsingError({
3030
expectation: exampleURL.pathname,
3131
reality : givenSubject,
32-
}).throwAnyway();
32+
}).throwAnyway('To be converted to `Attempt` failure');
3333

3434
return new URLPath(exampleURL.pathname);
3535
}

src/library/customTypes/UniformResourceIdentifier/Data/Image/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ class ImageURI extends DataURI {
5252

5353
if (
5454
proposedURI.mediaType.fileType !== ImageURI.mediaType
55-
) return new ImageURI_ParsingError(`Expected media type starting with ${ImageURI.mediaType}`).throwAnyway();
55+
) return new ImageURI_ParsingError(`Expected media type starting with ${ImageURI.mediaType}`).throwAnyway('To be converted to `Attempt` failure');
5656

5757
const format = allImageURIFormats.find($0 => $0 === proposedURI.mediaType.fileSubtype);
5858

5959
if (
6060
format === undefined
61-
) return new ImageURI_ParsingError(`Expected format to be one of ${allImageURIFormats.toString()}`).throwAnyway();
61+
) return new ImageURI_ParsingError(`Expected format to be one of ${allImageURIFormats.toString()}`).throwAnyway('To be converted to `Attempt` failure');
6262

6363
return new ImageURI(
6464
format,

src/library/customTypes/UniformResourceIdentifier/Data/MediaType/index.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ class MediaType implements StaticStringParser<typeof MediaType> {
103103

104104
if (
105105
!isEmpty(componentsFollowingUnexpectedFileTypeSuffix)
106-
) return new MediaType_ParsingError(`Found component sets after extraneous file type suffix(es): ${componentsFollowingUnexpectedFileTypeSuffix.toString()}`).throwAnyway();
106+
) return new MediaType_ParsingError(`Found component sets after extraneous file type suffix(es): ${componentsFollowingUnexpectedFileTypeSuffix.toString()}`).throwAnyway('To be converted to `Attempt` failure');
107107

108108
const fileType = allFileTypes.find($0 => $0 === rawFileType);
109109

110110
if (
111111
fileType === undefined
112-
) return new MediaType_ParsingError(`Expected file type as one of ${allFileTypes.toString()}`).throwAnyway();
112+
) return new MediaType_ParsingError(`Expected file type as one of ${allFileTypes.toString()}`).throwAnyway('To be converted to `Attempt` failure');
113113

114114
const [
115115
remainderBeforeParameters,
@@ -125,15 +125,15 @@ class MediaType implements StaticStringParser<typeof MediaType> {
125125

126126
if (
127127
!isEmpty(extraneousComponentsInEachParameter)
128-
) return new MediaType_ParsingError(`Found extraneous components in parameter at index ${indexOfEachParameter.toString()}: ${extraneousComponentsInEachParameter.toString()}`).throwAnyway();
128+
) return new MediaType_ParsingError(`Found extraneous components in parameter at index ${indexOfEachParameter.toString()}: ${extraneousComponentsInEachParameter.toString()}`).throwAnyway('To be converted to `Attempt` failure');
129129

130130
if (
131131
keyOfEachParameter === undefined
132-
) return new MediaType_ParsingError(`Expected key for parameter at index ${indexOfEachParameter.toString()}`).throwAnyway();
132+
) return new MediaType_ParsingError(`Expected key for parameter at index ${indexOfEachParameter.toString()}`).throwAnyway('To be converted to `Attempt` failure');
133133

134134
if (
135135
valueOfEachParameter === undefined
136-
) return new MediaType_ParsingError(`Expected value for parameter at index ${indexOfEachParameter.toString()}`).throwAnyway();
136+
) return new MediaType_ParsingError(`Expected value for parameter at index ${indexOfEachParameter.toString()}`).throwAnyway('To be converted to `Attempt` failure');
137137

138138
return [
139139
keyOfEachParameter,
@@ -149,7 +149,7 @@ class MediaType implements StaticStringParser<typeof MediaType> {
149149

150150
if (
151151
!isEmpty(extraComponentsWithStructureTypePrefix)
152-
) return new MediaType_ParsingError(`Unexpected component sets after extraneous structure type prefix(es): ${extraComponentsWithStructureTypePrefix.toString()}`).throwAnyway();
152+
) return new MediaType_ParsingError(`Unexpected component sets after extraneous structure type prefix(es): ${extraComponentsWithStructureTypePrefix.toString()}`).throwAnyway('To be converted to `Attempt` failure');
153153

154154
const structureType = (() => {
155155
if (rawStructureType === undefined) return null;
@@ -158,22 +158,22 @@ class MediaType implements StaticStringParser<typeof MediaType> {
158158

159159
if (
160160
potentialStructureType === undefined
161-
) return new MediaType_ParsingError(`Expected structure type as one of ${allStructuredSyntaxNameSuffix.toString()}`).throwAnyway();
161+
) return new MediaType_ParsingError(`Expected structure type as one of ${allStructuredSyntaxNameSuffix.toString()}`).throwAnyway('To be converted to `Attempt` failure');
162162

163163
return potentialStructureType;
164164
})();
165165

166166
if (
167167
serializedTreeBranchesEndingInFileSubtype === undefined
168-
) return new MediaType_ParsingError('Expected file subtype').throwAnyway();
168+
) return new MediaType_ParsingError('Expected file subtype').throwAnyway('To be converted to `Attempt` failure');
169169

170170
const treeBranchesEndingInFileSubtype = serializedTreeBranchesEndingInFileSubtype.split(MediaType.treeBranchSuffix);
171171
const reversedTreeBranchesBeginningWithFileSubtype = treeBranchesEndingInFileSubtype.reverse();
172172
const fileSubtype = reversedTreeBranchesBeginningWithFileSubtype.shift();
173173

174174
if (
175175
fileSubtype === undefined
176-
) return new MediaType_ParsingError('Expected file subtype').throwAnyway();
176+
) return new MediaType_ParsingError('Expected file subtype').throwAnyway('To be converted to `Attempt` failure');
177177

178178
const tree = reversedTreeBranchesBeginningWithFileSubtype.reverse();
179179

0 commit comments

Comments
 (0)