diff --git a/packages/openapi-typescript/src/lib/ts.ts b/packages/openapi-typescript/src/lib/ts.ts
index 3f795c60c..18bfa3a99 100644
--- a/packages/openapi-typescript/src/lib/ts.ts
+++ b/packages/openapi-typescript/src/lib/ts.ts
@@ -1,5 +1,7 @@
 import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";
+import type { Referenced, OasRef } from "@redocly/openapi-core";
 import ts, { type LiteralTypeNode, type TypeLiteralNode } from "typescript";
+import type { ParameterObject } from "../types.js";
 
 export const JS_PROPERTY_INDEX_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/;
 export const JS_ENUM_INVALID_CHARS_RE = /[^A-Za-z_$0-9]+(.)?/g;
@@ -115,33 +117,77 @@ export function addJSDocComment(schemaObject: AnnotatedSchemaObject, node: ts.Pr
   }
 }
 
-/** Convert OpenAPI ref into TS indexed access node (ex: `components["schemas"]["Foo"]`) */
-export function oapiRef(path: string): ts.TypeNode {
+function isOasRef<T>(obj: Referenced<T>): obj is OasRef {
+  return Boolean((obj as OasRef).$ref);
+}
+type OapiRefResolved = Referenced<ParameterObject>;
+
+function isParameterObject(obj: OapiRefResolved | undefined): obj is ParameterObject {
+  return Boolean(obj && !isOasRef(obj) && obj.in);
+}
+
+function addIndexedAccess(node: ts.TypeReferenceNode | ts.IndexedAccessTypeNode, ...segments: readonly string[]) {
+  return segments.reduce((acc, segment) => {
+    return ts.factory.createIndexedAccessTypeNode(
+      acc,
+      ts.factory.createLiteralTypeNode(
+        typeof segment === "number"
+          ? ts.factory.createNumericLiteral(segment)
+          : ts.factory.createStringLiteral(segment),
+      ),
+    );
+  }, node);
+}
+
+/**
+ * Convert OpenAPI ref into TS indexed access node (ex: `components["schemas"]["Foo"]`)
+ * `path` is a JSON Pointer to a location within an OpenAPI document.
+ * Transform it into a TypeScript type reference into the generated types.
+ *
+ * In most cases the structures of the openapi-typescript generated types and the
+ * JSON Pointer paths into the OpenAPI document are the same. However, in some cases
+ * special transformations are necessary to account for the ways they differ.
+ *   * Object schemas
+ *       $refs into the `properties` of object schemas are valid, but openapi-typescript
+ *       flattens these objects, so we omit  so the index into the schema skips ["properties"]
+ *   * Parameters
+ *       $refs into the `parameters` of paths are valid, but openapi-ts represents
+ *       them according to their type; path, query, header, etc… so in these cases we
+ *       must check the parameter definition to determine the how to index into
+ *       the openapi-typescript type.
+ **/
+export function oapiRef(path: string, resolved?: OapiRefResolved): ts.TypeNode {
   const { pointer } = parseRef(path);
   if (pointer.length === 0) {
     throw new Error(`Error parsing $ref: ${path}. Is this a valid $ref?`);
   }
-  let t: ts.TypeReferenceNode | ts.IndexedAccessTypeNode = ts.factory.createTypeReferenceNode(
-    ts.factory.createIdentifier(String(pointer[0])),
+
+  const parametersObject = isParameterObject(resolved);
+
+  // Initial segments are handled in a fixed , then remaining segments are treated
+  // according to heuristics based on the initial segments
+  const initialSegment = pointer[0];
+  const leadingSegments = pointer.slice(1, 3);
+  const restSegments = pointer.slice(3);
+
+  const leadingType = addIndexedAccess(
+    ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(String(initialSegment))),
+    ...leadingSegments,
   );
-  if (pointer.length > 1) {
-    for (let i = 1; i < pointer.length; i++) {
-      // Skip `properties` items when in the middle of the pointer
-      // See: https://github.com/openapi-ts/openapi-typescript/issues/1742
-      if (i > 2 && i < pointer.length - 1 && pointer[i] === "properties") {
-        continue;
-      }
-      t = ts.factory.createIndexedAccessTypeNode(
-        t,
-        ts.factory.createLiteralTypeNode(
-          typeof pointer[i] === "number"
-            ? ts.factory.createNumericLiteral(pointer[i])
-            : ts.factory.createStringLiteral(pointer[i] as string),
-        ),
-      );
+
+  return restSegments.reduce<ts.TypeReferenceNode | ts.IndexedAccessTypeNode>((acc, segment, index, original) => {
+    // Skip `properties` items when in the middle of the pointer
+    // See: https://github.com/openapi-ts/openapi-typescript/issues/1742
+    if (segment === "properties") {
+      return acc;
     }
-  }
-  return t;
+
+    if (parametersObject && index === original.length - 1) {
+      return addIndexedAccess(acc, resolved.in, resolved.name);
+    }
+
+    return addIndexedAccess(acc, segment);
+  }, leadingType);
 }
 
 export interface AstToStringOptions {
diff --git a/packages/openapi-typescript/src/transform/parameters-array.ts b/packages/openapi-typescript/src/transform/parameters-array.ts
index be995b75a..c28aac0ea 100644
--- a/packages/openapi-typescript/src/transform/parameters-array.ts
+++ b/packages/openapi-typescript/src/transform/parameters-array.ts
@@ -92,7 +92,7 @@ export function transformParametersArray(
       }
       const subType =
         "$ref" in original
-          ? oapiRef(original.$ref)
+          ? oapiRef(original.$ref, resolved)
           : transformParameterObject(resolved as ParameterObject, {
               ...options,
               path: createRef([options.path, "parameters", resolved.in, resolved.name]),
diff --git a/packages/openapi-typescript/test/fixtures/parameters-test.yaml b/packages/openapi-typescript/test/fixtures/parameters-test.yaml
index 1807eeed6..c16167f07 100644
--- a/packages/openapi-typescript/test/fixtures/parameters-test.yaml
+++ b/packages/openapi-typescript/test/fixtures/parameters-test.yaml
@@ -35,6 +35,9 @@ paths:
             type: string
         - $ref: "#/components/parameters/local_ref_b"
         - $ref: "./_parameters-test-partial.yaml#/remote_ref_b"
+  /endpoint2:
+    parameters: 
+      - $ref: "#/paths/~1endpoint/get/parameters/0"
 components:
   parameters:
     local_ref_a:
diff --git a/packages/openapi-typescript/test/index.test.ts b/packages/openapi-typescript/test/index.test.ts
index 8bd11b97f..f3fffc6e7 100644
--- a/packages/openapi-typescript/test/index.test.ts
+++ b/packages/openapi-typescript/test/index.test.ts
@@ -172,6 +172,25 @@ export type operations = Record<string, never>;`,
         patch?: never;
         trace?: never;
     };
+    "/endpoint2": {
+        parameters: {
+            query?: never;
+            header?: never;
+            path: {
+                /** @description This overrides parameters */
+                local_param_a: paths["/endpoint"]["get"]["parameters"]["path"]["local_param_a"];
+            };
+            cookie?: never;
+        };
+        get?: never;
+        put?: never;
+        post?: never;
+        delete?: never;
+        options?: never;
+        head?: never;
+        patch?: never;
+        trace?: never;
+    };
 }
 export type webhooks = Record<string, never>;
 export interface components {
diff --git a/packages/openapi-typescript/test/lib/ts.test.ts b/packages/openapi-typescript/test/lib/ts.test.ts
index e7a1fd992..afeee038c 100644
--- a/packages/openapi-typescript/test/lib/ts.test.ts
+++ b/packages/openapi-typescript/test/lib/ts.test.ts
@@ -65,15 +65,27 @@ describe("oapiRef", () => {
     expect(astToString(oapiRef("#/components/schemas/User")).trim()).toBe(`components["schemas"]["User"]`);
   });
 
-  test("removes inner `properties`", () => {
+  test("`properties` of component schema `properties`", () => {
     expect(astToString(oapiRef("#/components/schemas/User/properties/username")).trim()).toBe(
       `components["schemas"]["User"]["username"]`,
     );
   });
 
-  test("leaves final `properties` intact", () => {
+  test("component schema named `properties`", () => {
     expect(astToString(oapiRef("#/components/schemas/properties")).trim()).toBe(`components["schemas"]["properties"]`);
   });
+
+  test("reference into paths parameters", () => {
+    expect(
+      astToString(
+        oapiRef("#/paths/~1endpoint/get/parameters/0", {
+          in: "query",
+          name: "boop",
+          required: true,
+        }),
+      ).trim(),
+    ).toBe('paths["/endpoint"]["get"]["parameters"]["query"]["boop"]');
+  });
 });
 
 describe("tsEnum", () => {
diff --git a/packages/openapi-typescript/test/transform/webhooks-object.test.ts b/packages/openapi-typescript/test/transform/webhooks-object.test.ts
index f310d14e4..8a9c2e725 100644
--- a/packages/openapi-typescript/test/transform/webhooks-object.test.ts
+++ b/packages/openapi-typescript/test/transform/webhooks-object.test.ts
@@ -105,10 +105,10 @@ describe("transformWebhooksObject", () => {
                 schema: { type: "string" },
                 required: true,
               },
-              { $ref: "#/components/parameters/query/utm_source" },
-              { $ref: "#/components/parameters/query/utm_email" },
-              { $ref: "#/components/parameters/query/utm_campaign" },
-              { $ref: "#/components/parameters/path/version" },
+              { $ref: "#/components/parameters/utm_source" },
+              { $ref: "#/components/parameters/utm_email" },
+              { $ref: "#/components/parameters/utm_campaign" },
+              { $ref: "#/components/parameters/version" },
             ],
           },
         },
@@ -117,13 +117,13 @@ describe("transformWebhooksObject", () => {
         parameters: {
             query: {
                 signature: string;
-                utm_source?: components["parameters"]["query"]["utm_source"];
-                utm_email?: components["parameters"]["query"]["utm_email"];
-                utm_campaign?: components["parameters"]["query"]["utm_campaign"];
+                utm_source?: components["parameters"]["utm_source"];
+                utm_email?: components["parameters"]["utm_email"];
+                utm_campaign?: components["parameters"]["utm_campaign"];
             };
             header?: never;
             path: {
-                utm_campaign: components["parameters"]["path"]["version"];
+                utm_campaign: components["parameters"]["version"];
             };
             cookie?: never;
         };
@@ -141,28 +141,28 @@ describe("transformWebhooksObject", () => {
           ...DEFAULT_OPTIONS,
           resolve($ref) {
             switch ($ref) {
-              case "#/components/parameters/query/utm_source": {
+              case "#/components/parameters/utm_source": {
                 return {
                   in: "query",
                   name: "utm_source",
                   schema: { type: "string" },
                 };
               }
-              case "#/components/parameters/query/utm_email": {
+              case "#/components/parameters/utm_email": {
                 return {
                   in: "query",
                   name: "utm_email",
                   schema: { type: "string" },
                 };
               }
-              case "#/components/parameters/query/utm_campaign": {
+              case "#/components/parameters/utm_campaign": {
                 return {
                   in: "query",
                   name: "utm_campaign",
                   schema: { type: "string" },
                 };
               }
-              case "#/components/parameters/path/version": {
+              case "#/components/parameters/version": {
                 return {
                   in: "path",
                   name: "utm_campaign",